Go 1.11 will add preliminary support for versioned modules as proposed here.
Go modules will be an experimental opt-in feature in Go 1.11, with the hope of incorporating feedback and finalizing the feature for Go 1.12. Even though the details may change, future releases will support modules defined using Go 1.11 or vgo.
vgo tool, but on July 12, 2018 support for versioned Go modules landed in the main Go repository (announcement thread).vgo.master for the go mod commands. See faq below for an overview.NOTE: One current significant issue is that some older versions of git are not working:
master but not fixed in 1.11 beta2).To use modules, you currently have three install options:
master branch.go with go1.11beta2 in the commands below).vgo binary from the vgo subrepository (and replace go with vgo in the commands below).As of July 23, 2018, there are some recommendations (e.g., here) to currently prefer installing from source or the latest beta over using vgo.
Once installed, you can then activate module support in one of three ways:
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).go command with GO111MODULE=on in the command environment.vgo (if you have installed vgo from the subrepository).Go modules must be semantically versioned in the form v(major).(minor).(patch) (for example, v0.1.0, v1.2.3, or v3.0.1). If using Git, tag released commits with their versions. (Stand-alone distributed module repositories, such as Project Athens, are in the works.)
The major version of a module must be included in both the module path and the package import path if the major version is v2 or higher. Module versions of v1 and v0 must not be included in the path. Modules with different paths are different modules. Thus me.io/my/mod is different than me.io/my/mod/v2 and both may be imported in a single build, which among other benefits allows a v1 module to be implemented in terms of its v2 replacement or vice versa.
The behavior of modules for existing packages with post-v1 tags is still in flux; an important related recent change was issue 26238, which substantially improved the behavior for existing packages with post-v1 tags.
Go packages now live in modules. The path of a module is a URL path where it may be found, and may include a major version at the end of the path (but nowhere else). Module source code may be located outside of $GOPATH. Two example modules are rsc.io/goversion and github.com/kardianos/vtest/v3.
Modules are defined by a go.mod file that lives in the root of the module. Module files may include comments and will look familiar to a go programmer. Here is an example go.mod file:
module github.com/kardianos/vmain/v3
require (
github.com/kardianos/vtest/v2 v2.0.2
)
There are 4 directives: “module”, “require”, “exclude”, “replace”. Module paths may be quoted but are not required to be.
Including major versions in import paths will produce incompatibilities with old versions of Go. To work around this prior versions of the go tool have been updated and released to continue building as before. (See issue 25069.)
exclude and replace directives only operate on the current (“main”) module. exclude and replace directives in modules other than the main module are ignored.
TODO: show example exclude and replace directives.
There are two ways to release a v2 (or higher) module version:
v2 directory and place a new go.mod file in that folder. The module path must end with /v2. Tag the release with v2.0.0.go.mod file to include a /v2 at the end of the module path. Tag the release with v2.0.0.v2.*.* commits on a separate v2 branch.Packages are imported relative to the full module path, for example:
import "me.io/my/mod/v2/pkg" for package pkg in module me.io/my/mod/v2import "me.io/my/mod/pkg" for package pkg in module me.io/my/mod (v1 or v0).The default behavior when adding a new direct dependency via go commands such as ‘go get’ or ‘go build’ is to select the latest tagged release version (such as ‘v1.2.3’), which is recorded in the go.mod file with a require directive (such as require D v1.2.3). The minimal version selection algorithm is used to select the actual versions used in a build.
In general, the version of each module selected by minimal version selection and used in a build is always the semantically highest of the versions explicitly required by the module or one of its dependencies. This effectively locks versions into place until the module author or user chooses a new version explicitly or chooses to upgrade to the latest available minor or patch version.
For a brief overview and rationale for the minimal version selection algorithm, see the “High Fidelity Builds” section of the official proposal, or the more detailed vgo blog series.
Different major versions are distinct modules. For example, a /v2 module will never be compared with a /v3 module during minimal version selection.
To see a list of the selected module versions, use go list -m.
See also the “Upgrading and Downgrading Dependencies” section below and the “How are versions marked as incompatible?” FAQ below.
To create a go.mod for an existing project:
Navigate to the root of the module's source tree and activate module mode in the go command:
$ cd $GOPATH/src/<project path> $ export GO111MODULE=on
or:
$ cd <project path outside $GOPATH/src>
Create the initial module definition and write it to the go.mod file:
# if using go1.11beta2 or vgo: $ go mod -init # if using 'master', use the newer form: $ go mod init
This step converts from any existing dep Gopkg.lock file or from any of the other nine total supported dependency formats, adding require statements to match the existing configuration.
If go mod cannot determine an appropriate package path, or if you need to override that path, use the -module flag:
# if using go1.11beta2 or vgo: $ go mod -init -module example.com/my/module/v2 # if using 'master': $ go mod init example.com/my/module/v2
Build the module. This will automatically add missing or unconverted dependencies as needed to satisfy imports for this particular build invocation:
$ go build ./...
Test the module as configured to ensure that it works with the selected versions:
$ go test ./...
(Optional) Run the tests for all imported modules (direct and indirect dependencies) to check for incompatibilities:
$ go test all
Prior to tagging a release, see the Preparing a release section below.
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:
go get -u to use the latest minor or patch releasesgo get -u=patch to use the latest patch releasesTo 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, go get github.com/gorilla/mux@e3702bed2, or go get github.com/gorilla/mux@'<v1.6.2'.
See the “Module-aware go get” and “Module queries” sections of the tip documentation for more information on the topics here.
After upgrading or downgrading any dependencies, you may then want to run the tests again for all imported modules (direct and indirect dependencies) to check for incompatibilities:
$ go test all
Best practices for creating a release of a module are expected to emerge as part of the initial modules experiment. Many of these might end up being automated by a future ‘go release’ tool.
Some current suggested best practices to consider doing prior to tagging a release:
Run go mod -sync (or if using master: go mod tidy) to ensure your current go.mod reflects all possible build tags/OS/architecture combinations (as described here) and possibly prune any extraneous requirements (as described here).
Run go test all to test your module (including your direct and indirect dependencies) as a way of validating that the currently selected packages versions are compatible.
go test all has been re-defined to be more useful to include all the packages in the current module, plus all the packages they depend on through a sequence of one or more imports, while excluding packages that don't matter in the current module.go help modules for more about modules. (This is the main entry point for modules topics via go help)go help mod for more about the go mod command.go help module-get for more about the behavior of go get when in module-aware mode.go help goproxy for more about the module proxy, including a pure file-based option via a file:/// URL.vgo by Russ Cox (first posted February 20, 2018)vgo blog series, along with some of the history and process behind the proposalThe require directive allows any module to declare that it should be built with version >= x.y.z of a dependency D (which may be specified due to incompatibilities with version < x.y.z of module D). Empirical data suggests this is the dominant form of constraints used in dep and cargo. In addition, the top-level module in the build can exclude specific versions of dependencies or replace other modules with different code. See the full proposal for more details and rationale.
One of the key goals of the versioned modules proposal is to add a common vocabulary and semantics around versions of Go code for both tools and developers. This lays a foundation for future capabilities to declare additional forms of incompatibilities, such as:
vgo blog seriesHere is a sample list of improvements, almost all of which were primarily driven by community feedback:
go get -u=patch to update all transitive dependencies to the latest available patch-level versions on the same minor version (discussion, documentation)As part of the proposal, prototype, and beta process, there have been over 400 issues created by the overall community. Please continue to supply feedback.
go mod commands changed recently in master?As of July 31, 2018, there has been a significant change in master for the go mod commands. These changes are not in go1.11beta2. Two snippets from the CL briefly covering the rationale and the list of new vs. old commands:
The current "go mod" command does too many things. It looks like "everything you might want to do with modules" which causes people to think all module operations go through "go mod", which is the opposite of the seamless integration we're going for. In particular too many people think "go mod -require" and "go get" are the same.
and:
split "go mod" into multiple subcommands: go mod edit # old go mod -require ... go mod fix # old go mod -fix go mod graph # old go mod -graph go mod init # old go mod -init go mod tidy # old go mod -sync go mod vendor # old go mod -vendor go mod verify # old go mod -verify Splitting out the individual commands makes both the docs and the implementations dramatically easier to read. It simplifies the command lines (go mod -init -module m is now 'go mod init m') and allows command-specific flags.