概述
本文主要是根据 Modules 的翻译和实践操作。
Go Modules 是从 Go 1.11 开始,就引入了依赖管理工具,并在最近发布的 Go 1.14 开始稳定了,可以用于生产环境。Go 官方鼓励大家迁移到 Go Mod 来。
Quick Start
1
2
3
4
|
mkdir -p /tmp/scratchpad/repo
cd /tmp/scratchpad/repo
git init -q
git remote add origin https://github.com/my/repo
|
操作如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
➜ repo ls
➜ repo git init -q
➜ repo git:(master) git remote add origin https://github.com/my/repo
➜ repo git:(master) go mod init github.com/my/repo
# 这里报告初始化的结果,创建了一个额 go.mod 文件,并且这个是一个 module
go: creating new go.mod: module github.com/my/repo
➜ repo git:(master) ✗ tree
.
└── go.mod
0 directories, 1 file
➜ repo git:(master) ✗ cat <<EOF > hello.go
heredoc> package main
heredoc>
heredoc> import (
heredoc> "fmt"
heredoc> "rsc.io/quote"
heredoc> )
heredoc>
heredoc> func main() {
heredoc> fmt.Println(quote.Hello())
heredoc> }
heredoc> EOF
➜ repo git:(master) ✗ ls
go.mod hello.go
➜ repo git:(master) ✗ go build -o hello.go
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
➜ repo git:(master) ✗
➜ repo git:(master) ✗ ls
go.mod go.sum hello.go
➜ repo git:(master) ✗ cat go.mod
module github.com/my/repo
go 1.12
require rsc.io/quote v1.5.2
➜ repo git:(master) ✗ go list -m all
github.com/my/repo
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
➜ repo git:(master) ✗ go list -u -m all
github.com/my/repo
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c [v0.3.2]
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0 [v1.99.99]
➜ repo git:(master) ✗ go get -u ./...
go: finding golang.org/x/tools latest
go: finding golang.org/x/xerrors latest
go: finding golang.org/x/sys latest
go: finding golang.org/x/sync latest
go: finding golang.org/x/crypto latest
go: finding golang.org/x/net latest
package github.com/my/repo: read /tmp/scratchpad/repo/hello.go: unexpected NUL in input
➜ repo git:(master) ✗ go build
can't load package: package github.com/my/repo: read /tmp/scratchpad/repo/hello.go: unexpected NUL in input
➜ repo git:(master) ✗ vim hello.go
➜ repo git:(master) ✗ ls
go.mod go.sum hello.go
➜ repo git:(master) ✗ rm hello.go
➜ repo git:(master) ✗ cat <<EOF > hello.go
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
EOF
➜ repo git:(master) ✗ go build -o hello
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99
➜ repo git:(master) ✗ ls
go.mod go.sum hello hello.go
➜ repo git:(master) ✗ ./hello
99 bottles of beer on the wall, 99 bottles of beer, ...
➜ repo git:(master) ✗ ./hello
99 bottles of beer on the wall, 99 bottles of beer, ...
➜ repo git:(master) ✗ vi hello.go
➜ repo git:(master) ✗
➜ repo git:(master) ✗
➜ repo git:(master) ✗ ls
go.mod go.sum hello hello.go
➜ repo git:(master) ✗ go go.mod go
➜ repo git:(master) ✗ go mod tidy
➜ repo git:(master) ✗ ls
go.mod go.sum hello hello.go
➜ repo git:(master) ✗ cat go.mod
module github.com/my/repo
go 1.12
require (
golang.org/x/text v0.3.2 // indirect
rsc.io/quote v1.5.2
rsc.io/sampler v1.99.99 // indirect
)
➜ repo git:(master) ✗ cat go.sum
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
➜ repo git:(master) ✗ go mod vendor
➜ repo git:(master) ✗ ls
go.mod go.sum hello hello.go vendor
➜ repo git:(master) ✗ cd vendor
➜ vendor git:(master) ✗ ls
golang.org modules.txt rsc.io
➜ vendor git:(master) ✗ tree
|
查看 go.mod
文件,可以发下增加了几行,主要是针对依赖的,通过 require
来指定了依赖和精确的版本。
1
2
3
4
5
|
$ cat go.mod
module github.com/my/repo
require rsc.io/quote v1.5.2
|
所以,整个过程,是不是没见到烦人的 go get
?是的,所以用了 go mod
之后,你的日常工作可能会变成下面这样。
- 给你的
.go
源码引入依赖
- 在日常测试和开发中难免会需要
go build
和 go test
,通过这些日常操作,go mod
会自动去定位和下载满足条件的依赖
- 如果你需要非常精确的依赖版本,可以通过
go get foo@v1.23
或者 go get foo@master
又或者指定 commit id
比如 go get foo@44jbasf
,甚至直接去改 go.mod
文件都可以
1
2
3
4
5
6
7
|
go list -m all — 可以看到所有会用于构建的直接和间接依赖的版本
go list -u -m all — 可以看到所有会用于构建的直接和间接依赖的版本,并且升级那些需要升级的依赖
go get -u ./... or go get -u=patch ./... (from module root directory) — 同上但是会忽略依赖的 pre-releases
go build ./... or go test ./... (from module root directory) — 构建和测试
go mod tidy — 检查 go.mod 去删除不需要的依赖,and add any dependencies needed for other combinations of OS, architecture, and build tags (details)
replace directive or gohack — 如果直接引用依赖有问题,那么可以使用本地的拷贝版本,或者自己的 fork
go mod vendor — 可以构建 vendor 目录
|
Modules
module 是一系列的 Go 包组成的单位结构。记录了精确的依赖。一个 repo 一般就是一个 module,但是也会有一个 repo 里包含多个 module 的情况(找出来例子)。
现在用户需要区分几个概念,repo, modules 和 packages。
Migration Topics
Go 有非常多的包管理工具,不过 go mod init
可以做到几乎所有原有的包管理工具的自动迁移。比如说 dep, glide, govendor, godep 等等。
module declares its path as
这需要用到 go mod
的 replace
来调整,具体就是往 go.mod
插入一条记录。
1
|
replace github.com/coreos/bbolt v1.3.4 => go.etcd.io/bbolt v1.3.4
|
used for two different module paths
很神奇,replace
两次就好了,具体原因待排查。
1
|
go mod edit -replace=go.etcd.io/bbolt@v1.3.4=github.com/coreos/bbolt@v1.3.4
|
其实就会在 go.mod 文件插入两行。
1
2
|
replace github.com/coreos/bbolt v1.3.4 => go.etcd.io/bbolt v1.3.4
replace go.etcd.io/bbolt v1.3.4 => github.com/coreos/bbolt v1.3.4
|
410 Gone
这个通常是因为 Go 的版本不同导致的,如果你正在使用 Go 1.13 以上的版本,通过 GOSUMDB
的环境变量调整就可以了。
1
2
|
export GOSUMDB=off
go mod download
|
参考资料
- Modules
警告
本文最后更新于 2022年10月19日,文中内容可能已过时,请谨慎参考。