(June, August 2018, March 2019)
Go 1.11 introduces experimental support for modules, Go’s new dependency management system. Go 1.12 is expected to finalize the feature.
Go has cycled through a number of potential package management solutions.
Modules come from the experimental vgo
, and will soon be the official tool.
How do Go modules help us?
$GOPATH
.How does it work?
https://github.com/golang/go/wiki/Modules
A module is a collection of related Go packages that are versioned together as a single unit. Most often, a single version-control repository corresponds exactly to a single module, but alternatively a single version-control repository can hold multiple modules.
https://blog.golang.org/using-go-modules
A module is a collection of Go packages stored in a file tree with a
go.mod
file at its root. The go.mod file defines the module’s module path, which is also the import path used for the root directory, and its dependency requirements, which are the other modules needed for a successful build. Each dependency requirement is written as a module path and a specific semantic version.
$GOPATH
will eventually fade away, and modules take the first step in that direction.
By default, module support currently is disabled inside $GOPATH
, so we create our module outside it.
$ mkdir ~/mymodule
$ cd ~/mymodule
Create a file:
package mymodule
import "fmt"
// Hello to the world!
func Hello(s string) string {
return fmt.Sprintf("Hello, %s", s)
}
Turn our little package into a module:
$ go mod init example.com/me/mymodule
go: creating new go.mod: module example.com/me/mymodule
Go has created the new file go.mod
, which contains:
module module example.com/me/mymodule
Before Go modules, anyone who included our code and did go get example.com/me/mything
would get the latest version from the master branch.
The consumer of the code was left at the mercy of whatever changes landed in master.
Various workarounds, like vendoring, ameliorated the problem, but Go modules properly solve it.
With Go modules we can specify a particular version of code to import. Instead of fetching the latest master, by default, without specification of a particular version, Go will fetch the latest tagged version.
As an author, we should tag release versions of our module.
See git-tag(1)
.
$ git tag v1.2.0
$ git push --tags
This tags the current commit as v1.2.0
.
Go wants versions to be numbered like v2.0.13
, i.e. — vMajor.Minor.Patch
.
Because a major version change may (by definition) break backwards-compatibility, Go treats different major version of the same code as different modules.
We don’t do go get example.com/her/thing
.
Instead, enable modules for our project like:
$ cd myproject
$ go mod init mod
This creates a go.mod
file that contains a list of required modules, and a go.sum
file that includes numbered versions and checksums of modules.
Remember to add go.mod
and go.sum
to version control.
Go only updates a module when we explicitly ask it:
go get -u
updates modules to their most recent minor or patch version.go get -u=patch
updates modules to the latest patch for our minor version.go get example.com/her/thing@v1.4.15
gets a particular version.Update all dependencies in the current directory and all subdirectories:
$ go get -u ./...
$ go mod tidy
How do we jump to a different major module version?
Specify it on the import
line:
package main
import (
"fmt"
"example.com/her/thing/v2"
Running go build
then automatically fetches version 2.
Note that because Go considers different major version as different modules, it’s possible to import multiple versions:
package main
import (
"fmt"
"example.com/her/thing/v2"
oldThing "example.com/her/thing/"
Pull all of our dependencies into our go.mod
file:
$ go get -u ./...
Vendor those dependencies:
$ go mod vendor
List the modules used by the project:
$ go list -m all
Modules hang around in go.mod
even after we no longer import them or change major version.
Clean unused modules from the module list with:
$ go mod tidy
It’s nice to tidy before tagging a release.
Vendoring. Go modules to obviate many arguments for vendoring, but vendoring is supported by the Go module tool.
$ go mod vendor
$ go build -mod vendor
Get help:
$ go help modules | less
If something gets borked, like a cached package was incompletely downloaded:
$ go clean -modcache