At the earliest time, all third-party libraries that Go language depends on were placed under the GOPATH directory, which resulted in only one version of the code being saved for the same library. How should different projects that depend on different versions of the same third-party library be resolved?
Go module is the version management tool officially introduced by Go language since version 1.11, and starting from version 1.13, go module has become the default dependency management tool for Go language.
The commonly used go mod
commands are shown in the following table:
Command | Function |
---|---|
go mod download | Download dependencies to local (default to GOPATH/pkg/mod directory) |
go mod edit | Edit go.mod file |
go mod graph | Print module dependency graph |
go mod init | Initialize the current folder and create go.mod file |
go mod tidy | Add missing packages and remove unused packages |
go mod vendor | Copy dependencies to the vendor directory |
go mod verify | Dependency verification |
go mod why | Explain why dependencies are needed |
GOPROXY#
Proxy means proxy server. As we all know, there is a firewall in the domestic network, which makes it impossible for us to directly obtain some third-party packages of Go language through the go get
command. GOPROXY is a way provided by the official Go language to provide package download services for users through intermediate proxy vendors. To use GOPROXY, you only need to set the environment variable GOPROXY.
Currently, the addresses of publicly available proxy servers are:
- goproxy.io;
- goproxy.cn: (recommended) provided by Qiniu Cloud in China.
The command to set GOPROXY under MacOS or Linux is:
export GOPROXY=https://goproxy.cn
After Go language 1.13, the default value of GOPROXY is https://proxy.golang.org. In China, there may be slow downloads or inaccessible situations, so it is highly recommended to set GOPROXY to goproxy.cn in China.
Downloading specific versions of dependencies using the go get command#
Execute the go get
command to download dependencies and specify the version of the dependency package at the same time.
- Running the
go get -u
command will upgrade the packages in the project to the latest minor version or patch version; - Running the
go get -u=patch
command will upgrade the packages in the project to the latest patch version; - Running the
go get [package name]@[version]
command will download the specified version of the corresponding package or upgrade the corresponding package to the specified version.
Note: The version number in thego get [package name]@[version]
command can be in the form of x.y.z, such as go get foo@v1.2.3, or it can be a branch or tag on Git, such as go get foo@master, or it can be a hash value when committing on Git, such as go get foo@e3702bed2.
How to use in a project#
[Example 1] Create a new project:
- Create a new directory outside of GOPATH and use
go mod init
to initialize and generate the go.mod file.
go mod init hello
go: creating new go.mod: module hello
Once the go.mod file is created, its content will be fully controlled by the go toolchain. The go toolchain will modify and maintain the go.mod file when various commands are executed, such as go get
, go build
, go mod
, etc.
go.mod provides four commands: module, require, replace, and exclude:
- The module statement specifies the name (path) of the package;
- The require statement specifies the dependent module;
- The replace statement can replace the dependent module;
- The exclude statement can ignore the dependent module.
The go.mod file generated by initialization is as follows:
module hello
go 1.13
- Add dependencies.
Create a new main.go file and write the following code:
1. package main
3. import (
4. "net/http"
5. "github.com/labstack/echo"
6. )
8. func main() {
9. e := echo.New()
10. e.GET("/", func(c echo.Context) error {
11. return c.String(http.StatusOK, "Hello, World!")
12. })
13. e.Logger.Fatal(e.Start(":1323"))
14. }
Running go run main.go
will automatically find and download dependencies:
go run main.go
go: finding github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: extracting github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/labstack/gommon v0.3.0
......
go: finding golang.org/x/text v0.3.0
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:1323
Now check the content of go.mod:
module hello
go 1.13
require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.3.0 // indirect
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 // indirect
)
The principle of go module installation package is to first pull the latest release tag. If there is no tag, it will pull the latest commit. For details, please refer to the Modules Official introduction.
Go will automatically generate a go.sum file to record the dependency tree:
github.com/davecgh/go-spew v1.1.0/go.mod h1/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/labstack/echo v3.3.10+incompatible h1=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.3.0 h1=
github.com/labstack/gommon v0.3.0/go.mod h1+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
... omitted many lines
Run the script go run main.go
again and you will find that the check and installation of dependencies are skipped.
You can use the command go list -m -u all
to check the packages that can be upgraded, and use go get -u need-upgrade-package
to upgrade. The new dependency version will be updated to go.mod. * You can also use go get -u
to upgrade all dependencies.
[Example 2] Refactor an existing project.
The project directory structure is:
├─ main.go
│
└─ api
└─ apis.go
The source code of main.go is:
1. package main
3. import (
4. api "./api" // Use relative path here
5. "github.com/labstack/echo"
6. )
8. func main() {
9. e := echo.New()
10. e.GET("/", api.HelloWorld)
11. e.Logger.Fatal(e.Start(":1323"))
12. }
The source code of api/apis.go is:
1. package api
3. import (
4. "net/http"
6. "github.com/labstack/echo"
7. )
9. func HelloWorld(c echo.Context) error {
10. return c.JSON(http.StatusOK, "hello world")
11. }
- Use
go mod init ***
to initialize go.mod.
go mod init hello
go: creating new go.mod: module hello
- Run
go run main.go
.
go run main.go
go: finding golang.org/x/crypto latest
build _/D_/code/src/api: cannot find module for path _/D_/code/src/api
First, it will still find and download dependencies, and then run the main.go script. Here, an error is thrown:
build /D/code/src/api: cannot find module for path /D/code/src/api
But go.mod has been updated:
module hello
go 1.13
require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.3.0 // indirect
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 // indirect
)
So why does this error occur?
This is because the way main.go uses internal packages is different from before. Since go.mod will scan all packages in the same working directory and change the import method, hello needs to be used as the prefix of the path. In other words, it needs to be written as import hello/api. The import ./api allowed by the GOPATH/dep mode in the past is no longer valid.
- Update the old package import method.
So main.go needs to be rewritten as:
1. package main
3. import (
4. api "hello/api" // Use relative path here
5. "github.com/labstack/echo"
6. )
8. func main() {
9. e := echo.New()
10. e.GET("/", api.HelloWorld)
11. e.Logger.Fatal(e.Start(":1323"))
12. }
Note: When using go mod under Go language version 1.11, you may encounter errors like go build github.com/valyala/fasttemplate: module requires go 1.12. If you encounter such problems that need to be upgraded to 1.12, just upgrade to Go language version 1.12 or above.