Go Mod

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
2
$ mkdir -p /tmp/scratchpad/hello
$ cd /tmp/scratchpad/hello

Initialize a new module:

1
2
3
$ go mod init github.com/you/hello

go: creating new go.mod: module github.com/you/hello

Write your code:

1
2
3
4
5
6
7
8
9
10
11
12
$ cat <<EOF > hello.go
package main

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

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

Build and run:

1
2
3
4
$ go build 
$ ./hello

Hello, world.

Note your go.mod file includes explicit versions for your dependencies:

1
2
3
4
5
$ cat go.mod

module github.com/you/hello

require rsc.io/quote v1.5.2

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
2
3
4
5
6
module github.com/my/thing

require (
github.com/some/dependency v1.2.3
github.com/another/dependency/v4 v4.0.0
)

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
2
3
4
5
6
project/
├── go.mod
├── bar
│ └── bar.go
└── foo
└── foo.go

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 variable GO111MODULE unset (or explicitly set to auto).

  • 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
2
$ export GO111MODULE=on                         # manually active module mode
$ cd $GOPATH/src/<project path> # e.g., cd $GOPATH/src/you/hello

Create the initial module definition and write it to the go.mod file:

1
2
3
4
5
6
7
$ go mod init
```

`go mod init` will often be able to use auxiliary data (such as VCS meta-data) to automatically determine the appropriate module path, but if `go mod init` states it can not automatically determine the module path, or if you need to otherwise override that path, you can supply the module path as follows:

``` bash
$ go mod init github.com/you/hello

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ go mod help
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.

Usage:

go mod <command> [arguments]

The commands are:

download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.