go/build: 当ReleaseTags与默认值不匹配时,模块支持被禁用,

qlfbtfca  于 6个月前  发布在  Go
关注(0)|答案(1)|浏览(46)

你正在使用的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 确实有。

相关问题