你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.16.5 linux/amd64
这个问题在最新版本中是否重现?
是的。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/aleks/.cache/go-build"
GOENV="/home/aleks/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/aleks/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/aleks/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.5"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/aleks/go/src/github.com/gopherjs/gopherjs/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2418058575=/tmp/go-build -gno-record-gcc-switches"
问题描述
go/build
通过调用 go list
命令实现模块支持,这非常好。不幸的是,如果 build.Context
与默认构建上下文(由构建二进制文件的Go版本决定)不同,这种功能就是无效的。我假设这个限制来自于你不能将 ReleaseTags
传递给 go list
命令的事实。
不幸的是,这种检查并不是特别有帮助,因为没有保证 PATH 中的 go
工具与程序构建的版本相匹配。一个典型的例子是作为预构建二进制分发的工具。
此外,当一个 go/build
用户试图将发布标签与他们正在使用的GOROOT匹配时,模块支持可能会静默关闭,这是令人惊讶且难以调试的行为。
可能的解决方案
更好的条件可能是检查 go version
是否与 ReleaseTags
匹配,并让库用户在需要时将 GOROOT/bin
添加到 PATH
中,或者也许甚至默认使用 GOROOT 中的 go list
。
此外,值得考虑在特定情况下是否合适使用静默回退。我可以看到回退允许我们保持与早期行为的兼容性,而这并不依赖于 go
工具或其版本。但也许在 GO111MODULE=on
被设置时禁用回退会是合理的?
关于 x/tools/go/packages
的附注
go/packages
通过不让用户一开始就设置 ReleaseTags
来避免这个问题。建议用户通过操作PATH来达到期望的效果。
对于建议使用 go/packages
而不是 go/build
的建议,由于以下两个原因,在我的情况下实现起来很困难:
- 已经有很多现有代码依赖于
go/build
,更新它需要大量的工作。 - 目前,
go/packages
似乎没有暴露关于嵌入式文件的任何信息,但go/build
确实有。
1条答案
按热度按时间rkue9o1l1#
比较 #46648 。