In Go 1.11, a new tool has arrived. It’s called go mod
.
Quick Start Example
The details are covered in the remainder of this page, but here is a simple example of creating a module from scratch.
Create a directory outside of your GOPATH:
1 | $ mkdir -p /tmp/scratchpad/hello |
Initialize a new module:
1 | $ go mod init github.com/you/hello |
Write your code:
1 | $ cat <<EOF > hello.go |
Build and run:
1 | $ go build |
Note your go.mod file includes explicit versions for your dependencies:
1 | $ cat go.mod |
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.
Modules record precise dependency requirements and create reproducible builds.
go.mod
A module is defined by a tree of Go source files with a go.mod file in the tree’s root directory. Module source code may be located outside of GOPATH.
go.mod files may include comments and will look familiar to a Go programmer. Here is an example go.mod file defining the module github.com/my/thing:
1 | module github.com/my/thing |
There are four directives: module
, require
, exclude
, replace
.
All of the packages in a module share a common prefix – the module path. The go.mod file defines the module path via the module directive. For example, if you are defining a module for two packages example.com/my/project/foo and example.com/my/project/bar, the first line in your go.mod file typically would be “module example.com/my/project”, and the corresponding on-disk structure could be:
1 | project/ |
exclude
and replace
directives only operate on the current (“main”) module. exclude
and replace
directives in modules other than the main module are ignored when building the main module. The replace
and exclude
statements therefore allow the main module complete control over its own build, without also being subject to complete control by dependencies.
In Go source code, packages are imported using the full path including the module, for example:
“import “example.com/my/module/v2/pkg/foo”” to import foo from the v2 version of module example.com/my/module.
Version Selection
If you add a new import to your source code that is not yet covered by a require
in go.mod, any go command run (e.g., ‘go build’) will automatically look up the proper module and add the highest version of that new direct dependency to your module’s go.mod as a require
directive. For example, if your new import corresponds to dependency M whose latest tagged release version is v1.2.3, your module’s go.mod will end up with require M v1.2.3
, which indicates module M is a dependency with allowed version >= v1.2.3 (and < v2, given v2 is considered incompatible with v1).
The minimal version selection algorithm is used to select the versions of all modules used in a build. For each module in a build, the version selected by minimal version selection is always the semantically highest of the versions explicitly listed by a require
directive in the main module or one of its dependencies.
As an example, if your module depends on module A which has a require D v1.0.0
, and your module also depends on module B which has a require D v1.1.1
, then minimal version selection would choose v1.1.1 of D to include in the build (given it is the highest listed require
version). This selection of v1.1.1 remains consistent even if some time later a v1.2.0 of D becomes available. This is an example of how the modules system provides 100% reproducible builds. When ready, the module author or user might choose to upgrade to the latest available version of D or choose an explicit version for D.
How to Use Modules
How to Install and Activate Module Support
To use modules, two install options are:
Install the latest Go 1.11 release.
Install the Go toolchain from source on the master branch.
Once installed, you can then activate module support in one of two ways:Invoke the go command in a directory outside of the
$GOPATH/src
tree, with a valid go.mod file in the current directory or any parent of it and the environment variableGO111MODULE
unset (or explicitly set toauto
).Invoke the go command with
GO111MODULE=on
environment variable set.
How to Define a Module
Most projects will follow the simplest approach of using a single module per repository, which typically would mean creating one go.mod file located in the root directory of a repository. (Multiple modules are supported in a single repository, but most often that would result in more work on an on-going basis than a single module per repository).
To create a go.mod for an existing project:
Navigate to the root of the module’s source tree outside of GOPATH:
1 | $ cd <project path outside $GOPATH/src> # e.g., cd ~/projects/hello |
Note that outside of GOPATH, you do not need to set GO111MODULE to activate module mode.
Alternatively, if you want to work in your GOPATH:
1 | $ export GO111MODULE=on # manually active module mode |
Create the initial module definition and write it to the go.mod file:
1 | $ go mod init |
Build the module. This will automatically add missing or unconverted dependencies as needed to satisfy imports for this particular build invocation:
1 | $ go build ./... |
Test the module as configured to ensure that it works with the selected versions:
1 | $ go test ./... |
(Optional) Run the tests for your module plus the tests for all direct and indirect dependencies to check for incompatibilities:
1 | $ go test all |
How to Upgrade and Downgrade Dependencies
Day-to-day adding, removing, upgrading, and downgrading of dependencies should be done using ‘go get’, which will automatically update the go.mod file.
In addition, go commands like ‘go build’, ‘go test’, or even ‘go list’ will automatically add new dependencies as needed to satisfy imports (updating go.mod and downloading the new dependencies).
To upgrade to the latest version for all transitive dependencies of the current module:
- run
go get -u
to use the latest minor or patch releases - run
go get -u=patch
to use the latest patch releases
To upgrade or downgrade to a more specific version, ‘go get’ allows version selection to be overridden by adding an @version suffix or “module query” to the package argument, such as “go get github.com/gorilla/mux@v1.6.2” or “go get github.com/gorilla/mux@e3702bed2”.
“go get github.com/gorilla/mux” updates to the latest version with a semver tag. (This is equivalent to “go get github.com/gorilla/mux@latest” — in other words, @latest
is the default if no @
version is specified).
Using a branch name such as “go get github.com/gorilla/mux@master” is one way to obtain the latest commit regardless of whether or not it has a semver tag.
Commands
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands, not just ‘go mod’. For example, day-to-day adding, removing, upgrading, and downgrading of dependencies should be done using ‘go get’. See ‘go help modules’ for an overview of module functionality.
1 | $ go mod help |