Go modules are a collection of packages which share a single unit of versioning.
design goal: given the same set of initial dependencies always select the same set of all dependencies. (in contrast with SAT solvers which try to select the latest version of all dependencies)
check in go.mod
and go.sum
Go modules depends on modules following semver as defined by semver.org.
vX.Y.Z-a+b
X
: major version, increment on breaking changeY
: minor version, increment on new featureZ
: patch version, increment on bugfixa
: optional prerelease specifier, ordered alphabeticallyb
: optional build specifier, ignored in version selectionv0
and v1
share the same namespace and allow seamless upgrading
example: the following modules / versions are available
1module-a v0.1.0 v0.2.0 v0.3.0 v1.0.0 v1.1.0-alpha.1
2module-b v1.4.0 v1.5.0 v1.6.0 v2.0.0 v2.1.0
3module-c v0.7.0 v0.8.0 v0.9.0
if unspecified, select the latest released version with the current major version
example:
module-a
: v1.0.0
is selectedmodule-b
: v1.6.0
is selectedmodule-b/v2
: v2.1.0
is selectedexample:
module-a
requires module-c
@ v0.7.0
module-b
requires module-c
@ v0.8.0
v0.8.0
of module-c
is selectedBy default the go toolchain will use a public proxy https://proxy.golang.org
.
This offers faster querying and download speeds.
go env GOPROXY
check current settingsGOPROXY=direct
(fetches directly from source)GOPRIVATE
GOPRIVATE
to bypass the cachein go.mod
:
1module example.com/module
the first part of the name SHOULD have a dot in the name,
preferably domain like so go get
can work,
see vanity import paths.
Only test/
and example/
are reserved to not need a dot.
go mod init example.com/module
go mod init example.com/module/v2
go mod init github.com/seankhliao/testrepo
go mod init github.com/seankhliao/testrepo/v3
go mod init test/module
in go.mod
:
1go 1.X
Where 11 <= X <= current version
.
Lower versions guarantee the availability of features at that version,
but restrict the availability of newer versions.
Go does not automatically download older/newer toolchains,
but the current one will report a mismatch if it fails to build.
require example.com/module-a v1.2.3
require example.com/module-a v2.3.4 // +incompatible
require example.com/module-a v1.2.3-20200231-sdndsjcn
are only applied in the main module (the go build
is being run from)
replace example.com/module-a v1.2.3 => example.com/module-a v1.0.0
replace example.com/module-a => exmaple.com/module-a v1.0.0
replace example.com/module-a => example2.com/module-a v1.2.3
replace example.com/module-a => ../module-a
exclude example.com v1.2.3
go.sum
is not used for module selected / dependency resolution.
It is purely for security / integrity.
Do not worry about what's inside
Add the dependency in your code with import "example.com/module"
,
and run go run .
, go build
, go mod tidy
to automatically update go.mod
.
The latest version will be selected and recorded (if not already there).
go get example.com/module@latest
go get example.com/module@v1.2.3
go get example.com/module@master
(or any other branch)go get example.com/module@sj4jdn3
(or any commit)go get -u=patch example.com/module
go get -u example.com/module
go get -u all
go get -u ./...
Remove all imports in your code,
run go mod tidy
.
Vendoring is not necessary to guarantee the version of modules used, but you may want it to colocate your dependencies with your code, for auditing reasons, or for guaranteeing the availability of dependencies.
go mod vendor
vendor/
contents, do not modifyvendor/
automatically if the directory is available-mod=vendor
flagtag a new release
tag a new release
tag a new release
update go.mod
to new major version,
module example.com/module
=> module example.com/module/v2
module example.com/module/v2
=> module example.com/module/v3
update all internal imports to use the new import path (unless you want to depend on an older version of yourself)
import "example.com/module/package"
=> import "example.com/module/v2/package"
import "example.com/module/v2/package"
=> import "example.com/module/v3/package"
Sometimes you need to support legacy versions of go.
update go.mod
and imports as above, tag a new release.
example.com/module/v2
example.com/module
cut a new branch for every release (major / minor / patch depends on how much granularity you want to support).
example.com/module/v2
example.com/module
similar to the above approaches except the go1
branch has higher priority than the default branch
Keep all existing code.
Create a vX
subdirectory where X
== major version, ex v2
.
go mod init example.com/module/vX
in the directory and copy all the other code in.
example.com/module/v2
example.com/module/v2
go mod why
go mod graph
go list -m -f {{ ... }}