I have recently studied
go mod and have compiled it into an article. This article is a systematic look at
go mod, not a simple introduction to how to use it.
go mod came out, the community used a model similar to
vendor, which meant that all packages were stored in the
vendor directory, but this approach was obviously not elegant enough, and then came
go mod, which has become the standard for module management in the Go community until today.
- module. a folder with
go.modis a module. in short, a module that contains several packages.
- package. A number of
*.gofiles in a folder make up a package, and at the top of each
.gofile, there is a
package xxxto declare what package it is.
module has a version, Go adheres to Semantic Versioning 2.0.0, so versions will basically look like this:
v2.0.0 and so on. Some repositories don’t have a tag, so Go will automatically generate a version number, called
pseudo-version, which is a pseudo-version number, e.g.
v0.0.0-20191109021931-daa7c04131f5. The approximate format is.
- vX.0.0 base version
- Timestamp in the format yyyymmddhhmmss, the time value is the UTC time of that commit
- The first 12 characters of the commit hash
The three above, linked together with
Maybe we have a program that comes up
4.0, so what is the solution that Go offers? The answer is to create a subdirectory, e.g. for
v2 versions, create a
v2 subdirectory, for
v3 create a
v3 subdirectory. Or, if it’s at the top level, add a
v3 suffix to the end of the path declared in
To be honest, it’s not very elegant. His decision was largely based on the guideline that
If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.
This means that code within the same major version number must be compatible.
One of the problems with Go is that, for example, when upgrading from
v3, there may be some incompatibilities, but most of the code is still compatible and not completely rewritten. When you do this, the caller was importing
github.com/x/aaa, but now you have to import
github.com/x/aaa/v2, and all the references to it have to be changed. In addition, the
v2 and the
v1 are incompatible and cannot be assigned to each other, which causes the caller to change a lot of things and creates a lot of work.
GOPROXY, GOPRIVATE and other common environment variables
In areas where the network is restricted (e.g. China)
go getis basically not directly usable. So you can use the
GOPROXYenvironment variable to set up a proxy server.
$ go env -w GOPROXY="https://goproxy.cn,direct"
If your project is private then you will also need to add the corresponding path to the
$ go env -w GOPRIVATE="github.com/your_name,git.example.com"
If there is only one, write one. If there are more than one, concatenate them with commas. For private repositories, it is recommended to also set a
GONOSUMDBwith the same value as it.
As we said above, where there is a
go.mod file, there is a module, so let’s look at the format of
go.mod, starting with an example.
moduledeclares the path to the module itself
goDeclare the version of Go used by this module
requireDeclare the modules that this module depends on
excludetells the go mod not to load this module
replaceDeclare the replacement,
=>before the path in the code and after the path to replace it with
retractDeclare the version of this module that is broken, or the version to be withdrawn so that people don’t use it. The effect is that the user will be prompted when they encounter the version they have set
All the paths in there are in the format of a URL with a space and a version number, e.g.
How does go mod do version selection? In a nutshell: start with the current project
main, build a dependency tree, and when multiple submodules depend on the same module, choose the latest one.
As shown above,
main depends on
A1.2 depends on
C1.3 , while
B1.2 depends on
C1.4 and they also depend on
D1.2 . Finally,
go mod will select
There are times when we want to give a version to a subdirectory, so how do we do that? The answer is to just prefix the version number with the path to the directory, e.g.
Then we run
git tag A/B/v0.1.2 and that’s it. This way the user will give preference to the version of the subdirectory over the version number of the root directory when using the package.
Let’s look at common commands that have something to do with version control.
go mod init github.com/xxx/yyyDeclare a module
go mod tidyadds packages that the project depends on to the go.mod file, and removes packages in the go.mod file that the project doesn’t need.
go mod whyExplain the dependency chain of an imported dependency
go buildbuild the binary
go getadd dependencies
go get -uupdate dependencies