Go Modules:找出所需包的正确伪版本(vX.Y.Z-<timestamp>-<commit>)
Go Modules: finding out right pseudo-version (vX.Y.Z-<timestamp>-<commit>) of required package
我正在试用 Go 模块。我的项目需要库 golang.org/x/net/html
,所以我定义了这个 go.mod
文件:
module github.com/patrickbucher/prettyprint
require golang.org/x/net/html
并编写了这个演示程序来检查编译时是否加载了依赖项:
package main
import (
"fmt"
"log"
"os"
"golang.org/x/net/html"
)
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
log.Fatal(err)
}
fmt.Println(doc)
}
当我 运行 进行构建时,我收到此错误消息:
go: errors parsing go.mod:
~/prettyprint/go.mod:3: usage: require module/path v1.2.3
显然,我错过了版本号。但是拿哪一个呢?我偶然发现了一篇名为 Takig Go Modules for a Spin 的文章,在那里我找到了一个 go.mod
文件的示例,其中包含对 golang.org/x
包的引用:
module github.com/davecheney/httpstat
require (
github.com/fatih/color v1.5.0
github.com/mattn/go-colorable v0.0.9
github.com/mattn/go-isatty v0.0.3
golang.org/x/net v0.0.0-20170922011244-0744d001aa84
golang.org/x/sys v0.0.0-20170922123423-429f518978ab
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80
)
作者使用的版本字符串如 v0.0.0-20170922011244-0744d001aa84
,由 semver 指示 v0.0.0、时间戳和看起来像 git 提交 ID 的内容组成。
如何找出这些版本字符串?我猜这些 golang.org/x
包在某些时候会根据语义版本控制进行版本控制,但要真正尝试 go mod
,我需要弄清楚那些 now.
现在我进一步阅读了文档 (go help modules
) 并偶然发现 go mod tidy
:
The 'go mod tidy' command builds that view and then adds any missing
module requirements and removes unnecessary ones.
因此,当我放弃对 golang.org/x/net/html
的要求并 p运行e 我的 go.mod
文件时:
module github.com/patrickbucher/prettyprint
然后是运行go mod tidy
,然后根据我源码中的导入路径正确算出版本号的需求,然后因此 go.mod
变成:
module github.com/patrickbucher/prettyprint
require golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
现在 go list
和 go build
都可以使用了。
v0.0.0-20180906233101-161cd47e91fd
形式的版本意味着 git 存储库中没有标记的版本。所以go mod
根据最新的提交时间和提交哈希的前缀生成一个。
要获得正确的 go.mod
文件,请使用以下命令开始(假设 go 1.11):
go mod init yourmodulename
或者创建一个只包含以下内容的空 go.mod 文件:
module yourmodulename
然后运行 go mod tidy
,这将找到所有依赖项,添加缺少的并删除未使用的依赖项。
The author is using version strings like v0.0.0-20170922011244-0744d001aa84, consisting of the semver indication v0.0.0, a timestamp and something that looks like a git commit ID.
How do I figure out those version strings?
您永远不需要手动找出那些称为 pseudo-versions.
的复杂版本字符串
日常工作流程
您典型的日常工作流程可以是:
- 根据需要将导入语句添加到您的
.go
代码中。
go build
、go test
或 go mod tidy
等标准命令将根据需要自动添加新的依赖项以满足导入(更新 go.mod
并下载新的依赖项)。默认情况下,将使用新的直接依赖项的 @latest
版本。
- 需要时,可以使用以下命令选择更具体的依赖项版本:
go get foo@v1.2.3
go get foo@e3702bed2
go get foo@latest
go get foo@branch
- 或直接编辑
go.mod
。
请注意,在任何这些示例中,您都不需要自己提出伪版本,即使在请求特定提交(例如,@e3702bed2
)或最近一次提交时也是如此分支(例如,@master
)。
我什么时候会在 go.mod
中看到伪版本?
如果您最终在 go.mod
文件中得到一个解析为有效 semver tag with a leading v
such as v1.2.3
or v1.2.4-beta-1
, then that semver tag will be recorded in your go.mod
file. If the version does not have a valid semver tag, then it will be instead recorded with as a pseudo-version 的版本,例如 v0.0.0-20171006230638-a6e239ea1c69
,其中包括版本部分、提交时间戳和提交哈希。
在您的特定情况下,golang.org/x/net/html
没有任何 semver 标签,这意味着如果您执行 go get golang.org/x/net/html@latest
,或 go get golang.org/x/net/html@0744d001aa84
,或者先执行 go build
在你的 .go
文件中包含 import "golang.org/x/net/html"
,然后 golang.org/x/net/html 将作为伪版本记录在你的 go.mod
中,但请注意,你不需要弄清楚自己复杂的字符串(因为go
命令在需要的时候把modules queries比如go get golang.org/x/net/html@0744d001aa84
翻译成对应的伪版本,把结果记录在你的go.mod
里)。
为什么选择伪版本格式?
伪版本格式有助于提供基于标准 semver 排序的所有版本的简单总排序,这使得更容易推断出哪些提交将被视为 "later" 而不是另一个提交,或者是否将实际的 semver 标签视为 "later" 而不是单独的提交。
控制依赖版本
您可以在 Go Modules wiki 的 "How to Upgrade and Downgrade Dependencies" 部分阅读有关上述所有内容的更多信息,其中还包含指向官方文档的其他链接。
更新
此命令是将 replace
命令添加到 go.mod
的更好解决方案,而不是使用我最初发布的 git
手动执行:
go mod edit -replace github.com/docker/docker=github.com/docker/engine@ea84732a7725
产生类似的结果,但不是使用伪版本,而是找到标记的引擎版本。
replace github.com/docker/docker => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
或者,包括一个标记的 docker 版本。
go mod edit -replace github.com/docker/docker@v1.13.1=github.com/docker/engine@ea84732a7725
为
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
原始的、已弃用的答案
我是这样做的。
在所需 branch/tag 上检查存储库。例如
git clone -b v19.03.5 git@github.com:docker/engine.git
然后
cd engine
TZ=UTC git --no-pager show \
--quiet \
--abbrev=12 \
--date='format-local:%Y%m%d%H%M%S' \
--format="%cd-%h"
然后我得到
20191113042239-ea84732a7725
在go.mod
中用作
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v0.0.0-20191113042239-ea84732a7725
如果您想使用尚未标记的特定提交,您可以执行以下操作 -
module github.com/patrickbucher/prettyprint
require golang.org/x/net 73496e0df0ba4284f460d1955ddf6bb096957c9f
然后运行 go mod tidy
你会自动在go.mod文件中看到伪版本,变成
module github.com/patrickbucher/prettyprint
require golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
(我借用了上面 Patrick 的回复中的代码片段)
我正在试用 Go 模块。我的项目需要库 golang.org/x/net/html
,所以我定义了这个 go.mod
文件:
module github.com/patrickbucher/prettyprint
require golang.org/x/net/html
并编写了这个演示程序来检查编译时是否加载了依赖项:
package main
import (
"fmt"
"log"
"os"
"golang.org/x/net/html"
)
func main() {
doc, err := html.Parse(os.Stdin)
if err != nil {
log.Fatal(err)
}
fmt.Println(doc)
}
当我 运行 进行构建时,我收到此错误消息:
go: errors parsing go.mod:
~/prettyprint/go.mod:3: usage: require module/path v1.2.3
显然,我错过了版本号。但是拿哪一个呢?我偶然发现了一篇名为 Takig Go Modules for a Spin 的文章,在那里我找到了一个 go.mod
文件的示例,其中包含对 golang.org/x
包的引用:
module github.com/davecheney/httpstat
require (
github.com/fatih/color v1.5.0
github.com/mattn/go-colorable v0.0.9
github.com/mattn/go-isatty v0.0.3
golang.org/x/net v0.0.0-20170922011244-0744d001aa84
golang.org/x/sys v0.0.0-20170922123423-429f518978ab
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80
)
作者使用的版本字符串如 v0.0.0-20170922011244-0744d001aa84
,由 semver 指示 v0.0.0、时间戳和看起来像 git 提交 ID 的内容组成。
如何找出这些版本字符串?我猜这些 golang.org/x
包在某些时候会根据语义版本控制进行版本控制,但要真正尝试 go mod
,我需要弄清楚那些 now.
现在我进一步阅读了文档 (go help modules
) 并偶然发现 go mod tidy
:
The 'go mod tidy' command builds that view and then adds any missing module requirements and removes unnecessary ones.
因此,当我放弃对 golang.org/x/net/html
的要求并 p运行e 我的 go.mod
文件时:
module github.com/patrickbucher/prettyprint
然后是运行go mod tidy
,然后根据我源码中的导入路径正确算出版本号的需求,然后因此 go.mod
变成:
module github.com/patrickbucher/prettyprint
require golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
现在 go list
和 go build
都可以使用了。
v0.0.0-20180906233101-161cd47e91fd
形式的版本意味着 git 存储库中没有标记的版本。所以go mod
根据最新的提交时间和提交哈希的前缀生成一个。
要获得正确的 go.mod
文件,请使用以下命令开始(假设 go 1.11):
go mod init yourmodulename
或者创建一个只包含以下内容的空 go.mod 文件:
module yourmodulename
然后运行 go mod tidy
,这将找到所有依赖项,添加缺少的并删除未使用的依赖项。
The author is using version strings like v0.0.0-20170922011244-0744d001aa84, consisting of the semver indication v0.0.0, a timestamp and something that looks like a git commit ID.
How do I figure out those version strings?
您永远不需要手动找出那些称为 pseudo-versions.
的复杂版本字符串日常工作流程
您典型的日常工作流程可以是:
- 根据需要将导入语句添加到您的
.go
代码中。 go build
、go test
或go mod tidy
等标准命令将根据需要自动添加新的依赖项以满足导入(更新go.mod
并下载新的依赖项)。默认情况下,将使用新的直接依赖项的@latest
版本。- 需要时,可以使用以下命令选择更具体的依赖项版本:
go get foo@v1.2.3
go get foo@e3702bed2
go get foo@latest
go get foo@branch
- 或直接编辑
go.mod
。
请注意,在任何这些示例中,您都不需要自己提出伪版本,即使在请求特定提交(例如,@e3702bed2
)或最近一次提交时也是如此分支(例如,@master
)。
我什么时候会在 go.mod
中看到伪版本?
如果您最终在 go.mod
文件中得到一个解析为有效 semver tag with a leading v
such as v1.2.3
or v1.2.4-beta-1
, then that semver tag will be recorded in your go.mod
file. If the version does not have a valid semver tag, then it will be instead recorded with as a pseudo-version 的版本,例如 v0.0.0-20171006230638-a6e239ea1c69
,其中包括版本部分、提交时间戳和提交哈希。
在您的特定情况下,golang.org/x/net/html
没有任何 semver 标签,这意味着如果您执行 go get golang.org/x/net/html@latest
,或 go get golang.org/x/net/html@0744d001aa84
,或者先执行 go build
在你的 .go
文件中包含 import "golang.org/x/net/html"
,然后 golang.org/x/net/html 将作为伪版本记录在你的 go.mod
中,但请注意,你不需要弄清楚自己复杂的字符串(因为go
命令在需要的时候把modules queries比如go get golang.org/x/net/html@0744d001aa84
翻译成对应的伪版本,把结果记录在你的go.mod
里)。
为什么选择伪版本格式?
伪版本格式有助于提供基于标准 semver 排序的所有版本的简单总排序,这使得更容易推断出哪些提交将被视为 "later" 而不是另一个提交,或者是否将实际的 semver 标签视为 "later" 而不是单独的提交。
控制依赖版本
您可以在 Go Modules wiki 的 "How to Upgrade and Downgrade Dependencies" 部分阅读有关上述所有内容的更多信息,其中还包含指向官方文档的其他链接。
更新
此命令是将 replace
命令添加到 go.mod
的更好解决方案,而不是使用我最初发布的 git
手动执行:
go mod edit -replace github.com/docker/docker=github.com/docker/engine@ea84732a7725
产生类似的结果,但不是使用伪版本,而是找到标记的引擎版本。
replace github.com/docker/docker => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
或者,包括一个标记的 docker 版本。
go mod edit -replace github.com/docker/docker@v1.13.1=github.com/docker/engine@ea84732a7725
为
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
原始的、已弃用的答案
我是这样做的。
在所需 branch/tag 上检查存储库。例如
git clone -b v19.03.5 git@github.com:docker/engine.git
然后
cd engine
TZ=UTC git --no-pager show \
--quiet \
--abbrev=12 \
--date='format-local:%Y%m%d%H%M%S' \
--format="%cd-%h"
然后我得到
20191113042239-ea84732a7725
在go.mod
中用作
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v0.0.0-20191113042239-ea84732a7725
如果您想使用尚未标记的特定提交,您可以执行以下操作 -
module github.com/patrickbucher/prettyprint
require golang.org/x/net 73496e0df0ba4284f460d1955ddf6bb096957c9f
然后运行 go mod tidy
你会自动在go.mod文件中看到伪版本,变成
module github.com/patrickbucher/prettyprint
require golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
(我借用了上面 Patrick 的回复中的代码片段)