Blog

Victor is a full stack software engineer who loves travelling and building things. Most recently created Ewolo, a cross-platform workout logger.

    A quick introduction to Go modules

    This is a great time to jump into Go programming since starting with Go 1.12, we have module support and we don't have to have muck about with the GOPATH environment variable. This article is a quick introduction to Go modules and while the examples are provided for Ubuntu 18.04, the concepts are operating system agnostic.

    A Go module is a collection of related go packages. More specifically, a Go module is a tree of Go source files which have a go.mod file. This file contains the module import name, dependency requirements, exclusions and replacements.

    Assuming that go is already installed and available, let's see go modules in action. Before we begin however, note that the project directories below need to be outside your $GOPATH because Go module support is disabled inside it for backwards compatibility. Let's start by creating a module:

    $ mkdir hello-world-mod
    $ cd hello-world-mod
    $ vim hello-world-mod.go
    
    package helloworld
    
    import "fmt" 
    
    // Hello returns a friendly greeting
    func Hello(name string) string {
        return fmt.Sprintf("Hello, %s", name)
    }
    

    Now convert this package into a module via: go mod init github.com/smalldatatech/hello-world-mod. This creates a relevant go.mod file. We will now push and tag this module:

    $ git init 
    $ git add * 
    $ git commit -am "First commit" 
    $ git push -u origin master
    $ git tag v1.0.0
    $ git push --tags
    

    We can now use our freshly minted module in a project:

    $ mkdir ~/hello-world-go
    $ cd ~/hello-world-go
    $ go mod init github.com/smalldatatech/hello-world-go
    $ go get github.com/smalldatatech/hello-world-mod
    go: finding github.com/smalldatatech/hello-world-mod v1.0.0
    go: downloading github.com/smalldatatech/hello-world-mod v1.0.0
    go: extracting github.com/smalldatatech/hello-world-mod v1.0.0
    $ vim hello.go
    
    package main
    
    import (
    	"fmt"
    
    	helloworld "github.com/smalldatatech/hello-world-mod"
    )
    
    func main() {
    	fmt.Println(helloworld.Hello("Snoop"))
    }
    

    Test that this works via go run hello.go. Note that apart from go.mod, there is a go.sum file also created which contains cryptographic checksums of module dependencies. It is used to verify that cached dependencies meet module requirements.

    Go modules are integrated with Go tools and on invocation of commands (go build, go get, etc), actions such as populating the cache, creating or updating go.mod and go.sum will automagically happen.

    The following is an overview of module management commands:

    Initialize module
    go mod init <project-root-name>
    Vendor dependencies
    go mod vendor, this will create a vendor directory under the root of your project containing the source code for all dependencies. However, go build will ignore the contents of this directory by default. To build dependencies from the vendor directory run, go build -mod vendor
    Install/clean-up dependencies
    go mod tidy
    Pin a dependency
    go mod edit -require some/module@version or simply go get package@version
    Print dependency graph
    go mod graph
    Get help
    go help mod

    Note that the actual dependencies are stored under $GOPATH/pkg/mod which when using gvm translates to: ~/.gvm/pkgsets/go1.12.1/global/pkg/mod.

    Well that's about it, Go modules are really cool and they remind me a lot about Node.js package management, maybe even better since the dependencies are cached globally. Happy coding!

    References

    HackerNews submission / discussion

    Back to the article list.

    SmallData newsletter

    Subscribe to get articles as they are published direct to your inbox!