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 avendor
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 thevendor
directory run,go build -mod vendor
- Install/clean-up dependencies
go mod tidy
- Pin a dependency
go mod edit -require some/module@version
or simplygo 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!