使用 "go get" 下载二进制文件而不将它们添加到 go.mod
Using "go get" to download binaries without adding them to go.mod
我在我的项目和我的构建系统中使用 Go 模块(例如 Travis CI)我正在下载一个命令行实用程序(用 Go 编写)go get
来协助使用我的构建过程,例如:
go get github.com/mitchellh/gox
但是,这 go get
导致文件被添加到我的 go.mod
文件中。这污染了构建环境,导致它成为 "dirty"(因为在 git 中跟踪了一些文件的更改,在本例中为 go.mod 和 go.sum),并且我使用 git describe --always --dirty --tag
描述我的构建,显示为 "dirty".
有没有办法 "go get" 只下载一个二进制文件,而无需将其添加到 go 中。mod/go.sum?
我已经尝试将 GOPATH 设置到其他地方,即使那样,go get
也会更新 go.mod/go.sum 以将其添加为 // indirect
依赖项。
dir="$(mktemp -d)"; \
env GOPATH="$dir" go get github.com/mitchellh/gox && \
mv "$dir/bin/gox" "$(go env GOPATH)"/bin/gox
每 go help build
:
The -mod build flag provides additional control over updating and use of go.mod.
If invoked with -mod=readonly, the go command is disallowed from the implicit automatic updating of go.mod
希望在 Go 1.14 中会有一个 go get
的新标志,它完全符合您的要求。这在问题 #30515 "cmd/go: offer a consistent global install command".
中进行了跟踪
在此之前,您有几个不同的选择。
转到 1.12 和 1.13:更改目录
如果您使用的是 Go 1.12 或更高版本,最简单的解决方案可能是在执行 go get
之前将当前模块移出到一个没有 go.mod
的目录,例如:
$ cd /tmp
$ go get github.com/foo/bar@v1.2.3
$ cd - # return to prior directory
Go 1.11、1.12、1.13+:gobin
gobin is a module-aware command to install or run binaries that provides additional flexibility, including the ability to install without altering your current module's go.mod
. See the gobin
README and FAQ了解更多详情。
Go 1.11:临时模块
如果您使用带有模块的 Go 1.11,第一步可能是升级到 Go 1.12 或 1.13,因为模块有很多改进。如果您需要使用 Go 1.11 并且想使用 @version
语法而不更新当前模块的 go.mod
,那么一种方法是创建一个临时模块:
cd $(mktemp -d) && go mod init tempmod && go get github.com/foo/bar@v1.2.3
这是因为在 Go 1.11 中,除非在模块中,否则不能使用 @version
语法,这在 Go 1.12 中放宽了。 simple shell script by @rogpeppe.
已将此方法自动化
其他详细信息
一般来说,module-module中的go
命令总是会根据调用go
命令时的当前工作目录来判断它是什么模块"in"。 (您可以类比没有任何参数的 make
如何在当前工作目录中查找 makefile,或者历史上没有任何参数的 go build
将如何构建当前工作目录等)。
对于模块,go get
在当前工作目录或其任何父目录中查找 go.mod
文件,并且 go get
将使用任何 [=13= 中列出的约束] 作为解决版本问题的一部分,并在需要时根据 go get
更新 go.mod
。这就是为什么如果您从现有模块中 运行 go get
更新您的 go.mod
文件。
另一方面,从 Go 1.12 开始,如果您所在的目录不属于任何模块(也就是说,该目录没有 go.mod
,它的任何父目录也没有),则没有go.mod
更新,但go
命令仍然可以在模块模式下运行并使用@version
语法。
When GO111MODULE is set to on, the go command now supports module-aware operations outside of a module directory, provided that those operations do not need to resolve import paths relative to the current directory or explicitly edit the go.mod file. Commands such as go get, go list, and go mod download behave as if in a module with initially-empty requirements. In this mode, go env GOMOD reports the system's null device (/dev/null or NUL).
从 1.16 开始
Go 1.16(2021 年 2 月发布)包含一项更改,可以在不影响 go.mod
.
的情况下安装二进制文件
Issue 40276跟踪提案:
cmd/go: 'go install' should install executables in module mode outside a module
这是在 CL 254365 中实现的。作为此更改的一部分,您可以 运行 例如:
go install golang.org/x/tools/cmd/goimports@latest
在不影响 go.mod
的情况下安装二进制文件。
要安装特定版本,请将 @latest
替换为例如@v0.1.5
.
我在我的项目和我的构建系统中使用 Go 模块(例如 Travis CI)我正在下载一个命令行实用程序(用 Go 编写)go get
来协助使用我的构建过程,例如:
go get github.com/mitchellh/gox
但是,这 go get
导致文件被添加到我的 go.mod
文件中。这污染了构建环境,导致它成为 "dirty"(因为在 git 中跟踪了一些文件的更改,在本例中为 go.mod 和 go.sum),并且我使用 git describe --always --dirty --tag
描述我的构建,显示为 "dirty".
有没有办法 "go get" 只下载一个二进制文件,而无需将其添加到 go 中。mod/go.sum?
我已经尝试将 GOPATH 设置到其他地方,即使那样,go get
也会更新 go.mod/go.sum 以将其添加为 // indirect
依赖项。
dir="$(mktemp -d)"; \
env GOPATH="$dir" go get github.com/mitchellh/gox && \
mv "$dir/bin/gox" "$(go env GOPATH)"/bin/gox
每 go help build
:
The -mod build flag provides additional control over updating and use of go.mod.
If invoked with -mod=readonly, the go command is disallowed from the implicit automatic updating of go.mod
希望在 Go 1.14 中会有一个 go get
的新标志,它完全符合您的要求。这在问题 #30515 "cmd/go: offer a consistent global install command".
在此之前,您有几个不同的选择。
转到 1.12 和 1.13:更改目录
如果您使用的是 Go 1.12 或更高版本,最简单的解决方案可能是在执行 go get
之前将当前模块移出到一个没有 go.mod
的目录,例如:
$ cd /tmp
$ go get github.com/foo/bar@v1.2.3
$ cd - # return to prior directory
Go 1.11、1.12、1.13+:gobin
gobin is a module-aware command to install or run binaries that provides additional flexibility, including the ability to install without altering your current module's go.mod
. See the gobin
README and FAQ了解更多详情。
Go 1.11:临时模块
如果您使用带有模块的 Go 1.11,第一步可能是升级到 Go 1.12 或 1.13,因为模块有很多改进。如果您需要使用 Go 1.11 并且想使用 @version
语法而不更新当前模块的 go.mod
,那么一种方法是创建一个临时模块:
cd $(mktemp -d) && go mod init tempmod && go get github.com/foo/bar@v1.2.3
这是因为在 Go 1.11 中,除非在模块中,否则不能使用 @version
语法,这在 Go 1.12 中放宽了。 simple shell script by @rogpeppe.
其他详细信息
一般来说,module-module中的go
命令总是会根据调用go
命令时的当前工作目录来判断它是什么模块"in"。 (您可以类比没有任何参数的 make
如何在当前工作目录中查找 makefile,或者历史上没有任何参数的 go build
将如何构建当前工作目录等)。
对于模块,go get
在当前工作目录或其任何父目录中查找 go.mod
文件,并且 go get
将使用任何 [=13= 中列出的约束] 作为解决版本问题的一部分,并在需要时根据 go get
更新 go.mod
。这就是为什么如果您从现有模块中 运行 go get
更新您的 go.mod
文件。
另一方面,从 Go 1.12 开始,如果您所在的目录不属于任何模块(也就是说,该目录没有 go.mod
,它的任何父目录也没有),则没有go.mod
更新,但go
命令仍然可以在模块模式下运行并使用@version
语法。
When GO111MODULE is set to on, the go command now supports module-aware operations outside of a module directory, provided that those operations do not need to resolve import paths relative to the current directory or explicitly edit the go.mod file. Commands such as go get, go list, and go mod download behave as if in a module with initially-empty requirements. In this mode, go env GOMOD reports the system's null device (/dev/null or NUL).
从 1.16 开始
Go 1.16(2021 年 2 月发布)包含一项更改,可以在不影响 go.mod
.
Issue 40276跟踪提案:
cmd/go: 'go install' should install executables in module mode outside a module
这是在 CL 254365 中实现的。作为此更改的一部分,您可以 运行 例如:
go install golang.org/x/tools/cmd/goimports@latest
在不影响 go.mod
的情况下安装二进制文件。
要安装特定版本,请将 @latest
替换为例如@v0.1.5
.