Create a new package in Go using Go Modules

Go Modules

The purpose of this post is to give a very simple example and instructions on how to
create a Go package with the Go Modules.

Create a new package

Let’s start by creating a new repository (e.g. go-modules) and apply the following
folder/file structure to it:

go-modules
|-- bar
|   `-- bar.go
|-- foo
|   `-- foo.go
`-- main.go

Now run

$ go mod init gomodules

This will create go.mod file with the following structure:

module gomodules

go 1.13

Now let’s add an external dependency to our project:

$ go get rsc.io/quote

This will add require rsc.io/quote v1.5.2 // indirect to go.mod and it will also
create go.sum file with pinned packages.

Now let’s add some code.

Add this to main.go:

package main

import (
    "gomodules/foo"
    "gomodules/bar"
)

func main() {
    foo.Hello()
    bar.Hello()
}

Add this to foo/foo.go:

package foo

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}

Add this to bar/bar.go:

package bar

import (
    "fmt"
    "gomodules/foo"
)

func Hello() {
    fmt.Println("Hello from Bar.")
    foo.Hello()
}

Now run go build .. This will produce a file executable file named gomodules. If we run
it this is what the output should be:

$ ./gomodules
Hello, world.
Hello from Bar.
Hello, world.

The first Hello, world. is from calling foo.Hello() in main.go then we call bar.Hello()
which produces Hello from Bar. and Hello, world. because bar.Hello also calls
foo.Hello().

NOTE: Do not forget to name the public functions with a
capital letter
otherwise they won’t be available in main.go (because they won’t be exported).

Pin a package

Now let’s add another package but this time let’s pin it to a specific version:

$ go get github.com/liderman/text-generator@v0.1.0

If we would already have added text-generator we would need to use the -u (upgrade)
flag to apply the changes.

$ go get -u github.com/liderman/text-generator@v0.1.0

This will add github.com/liderman/text-generator v0.1.0 to go.mod file. The v0.1.0
refers to the github tag. You can see all tags/releases here: https://github.com/liderman/text-generator/releases
(for liderman/text-generator package).

Now let’s modify main.go file a bit to use our new package:


package main

import (
    "fmt"
    "github.com/liderman/text-generator"
    "gomodules/bar"
    "gomodules/foo"
)

func main() {
    foo.Hello()
    bar.Hello()

    tg := text_generator.New()
    template := "Good {morning|day}!"

    fmt.Println(tg.Generate(template))
}

Now we need to build the package again and run it:

$ go build
$ ./gomodules
Hello, world.
Hello from Bar.
Hello, world.
Good day!

Tidy your go.mod

To make sure that go.mod matches the source code in the module run go tidy:

$ go mod tidy

It adds any missing modules necessary to build the current module’s
packages and dependencies, and it removes unused modules that
don’t provide any relevant packages. It also adds any missing entries
to go.sum and removes any unnecessary ones.

See this article
using go list, go mod why and go mod graph.

What is the difference between package versions?

Using apidiff to determine API compatibility.


Ref:

Leave a Reply

Your email address will not be published. Required fields are marked *