在拉取项目依赖时,你会发现拉取的过程总共分为了三大步,分别是 finding(发现)、downloading(下载)以及 extracting(提取), 并且在拉取信息上一共分为了三段内容:
需要注意的是,所拉取版本的 commit 时间是以UTC时区为准,而并非本地时区,同时我们会发现我们 go get
命令所拉取到的版本是 v0.0.0,这是因为我们是直接执行 go get -u
获取的,并没有指定任何的版本信息,由 Go modules 自行按照内部规则进行选择。
# 1️⃣ go get 的拉取行为
刚刚我们用 go get
命令拉取了新的依赖,那么 go get
又提供了哪些功能呢,常用的拉取命令如下:
命令 | 作用 |
---|---|
go get | 拉取依赖,会进行指定性拉取(更新),并不会更新所依赖的其它模块。 |
go get -u | 更新现有的依赖,会强制更新它所依赖的其它全部模块,不包括自身。 |
go get -u -t ./... | 更新所有直接依赖和间接依赖的模块版本,包括单元测试中用到的。 |
那么我想选择具体版本应当如何执行呢,如下:
命令 | 作用 |
---|---|
go get golang.org/x/text@latest | 拉取最新的版本,若存在tag,则优先使用。 |
go get golang.org/x/text@master | 拉取 master 分支的最新 commit。 |
go get golang.org/x/text@v0.3.2 | 拉取 tag 为 v0.3.2 的 commit。 |
go get golang.org/x/text@342b2e | 拉取 hash 为 342b231 的 commit,最终会被转换为 v0.3.2。 |
# 2️⃣ go get 的版本选择
我们回顾一下我们拉取的 go get github.com/eddycjy/mquote
,其结果是 v0.0.0-20200220041913-e066a990ce6f
,对照着上面所提到的 go get
行为来看,你可能还会有一些疑惑,那就是在 go get
没有指定任何版本的情况下,它的版本选择规则是怎么样的,也就是为什么 go get
拉取的是 v0.0.0
,它什么时候会拉取正常带版本号的 tags 呢。实际上这需要区分两种情况,如下:
- 所拉取的模块有发布 tags:
- 如果只有单个模块,那么就取主版本号最大的那个tag。
- 如果有多个模块,则推算相应的模块路径,取主版本号最大的那个tag(子模块的tag的模块路径会有前缀要求)
- 所拉取的模块没有发布过 tags:
- 默认取主分支最新一次 commit 的 commithash。
没有发布过 tags
那么为什么会拉取的是 v0.0.0
呢,是因为 github.com/eddycjy/mquote
没有发布任何的tag,如下:
因此它默认取的是主分支最新一次 commit 的 commit 时间和 commithash,也就是 20200220041913-e066a990ce6f
,属于第二种情况。
有发布 tags
在项目有发布 tags 的情况下,还存在着多种模式,也就是只有单个模块和多个模块,我们统一以多个模块来进行展示,因为多个模块的情况下就已经包含了单个模块的使用了,如下图:
在这个项目中,我们一共打了两个tag,分别是:v0.0.1 和 module/tour/v0.0.1。这时候你可能会奇怪,为什么要打 module/tour/v0.0.1
这么“奇怪”的tag,这有什么用意吗?
其实是 Go modules 在同一个项目下多个模块的tag表现方式,其主要目录结构为:
mquote
├── go.mod
├── module
│ └── tour
│ ├── go.mod
│ └── tour.go
└── quote.go
2
3
4
5
6
7
可以看到在 mquote
这个项目的根目录有一个 go.mod 文件,而在 module/tour
目录下也有一个 go.mod 文件,其模块导入和版本信息的对应关系如下:
tag | 模块导入路径 | 含义 |
---|---|---|
v0.0.1 | github.com/eddycjy/mquote | mquote 项目的v 0.0.1 版本 |
module/tour/v0.01 | github.com/eddycjy/mquote/module/tour | mquote 项目下的子模块 module/tour 的 v0.0.1 版本 |
导入主模块和子模块
结合上述内容,拉取主模块的话,还是照旧执行如下命令:
$ go get github.com/eddycjy/mquote@v0.0.1
go: finding github.com/eddycjy/mquote v0.0.1
go: downloading github.com/eddycjy/mquote v0.0.1
go: extracting github.com/eddycjy/mquote v0.0.1
2
3
4
如果是想拉取子模块,执行如下命令:
$ go get github.com/eddycjy/mquote/module/tour@v0.0.1
go: finding github.com/eddycjy/mquote/module v0.0.1
go: finding github.com/eddycjy/mquote/module/tour v0.0.1
go: downloading github.com/eddycjy/mquote/module/tour v0.0.1
go: extracting github.com/eddycjy/mquote/module/tour v0.0.1
2
3
4
5
我们将主模块和子模块的拉取进行对比,你会发现子模块的拉取会多出一步,它会先发现 github.com/eddycjy/mquote/module
,再继续推算,最终拉取到 module/tour
。