Jay Conrod
2021年2月18日
我们希望您喜欢Go 1.16!此版本具有许多新功能,尤其是对于模块。该发行说明描述这些变化短暂,但让我们来看看其中的几个深入。
默认情况下开启模块
go
默认情况下,即使没有命令,该命令现在也默认以模块感知模式构建软件包go.mod
。这是在所有项目中使用模块的重要一步。
通过将GO111MODULE
环境变量设置为GOPATH模式仍然可以构建软件包off
。您还可以设置GO111MODULE
为auto
仅在当前目录或任何父目录中存在go.mod文件时启用模块感知模式。这以前是默认设置。请注意,您可以GO111MODULE
使用go env -w
以下命令永久设置和其他变量:
go env -w GO111MODULE=auto
我们计划在Go 1.17中放弃对GOPATH模式的支持。换句话说,Go 1.17将忽略GO111MODULE
。如果您的项目不是以模块感知模式构建的,那么现在该迁移了。如果存在阻止您迁移的问题,请考虑提交问题或经验报告。
不会自动更改go.mod和go.sum
此前,当go
命令发现问题,go.mod
或go.sum
像一个丢失的require
指令或丢失的总和,它会自动尝试解决这个问题。我们收到了很多反馈,认为这种行为令人惊讶,尤其是对于go list
通常没有副作用的命令。自动修复并非总是可取的:如果任何必需的模块未提供导入的软件包,则该go
命令将添加新的依赖项,从而可能触发常见依赖项的升级。甚至错误拼写的导入路径也会导致(失败的)网络查找。
在Go 1.16中,支持模块的命令在发现问题后go.mod
或go.sum
尝试自动修复问题时会报告错误。在大多数情况下,错误消息建议使用命令来解决此问题。
$ go build
example.go:3:8: no required module provides package golang.org/x/net/html; to add it:
go get golang.org/x/net/html
$ go get golang.org/x/net/html
$ go build
和以前一样,该go
命令可以使用vendor
目录(如果存在的话)(有关详细信息,请参见供应商)。命令likego get
且go mod tidy
仍会修改go.mod
and go.sum
,因为它们的主要目的是管理依赖项。
安装特定版本的可执行文件
go install
现在,该命令可以通过指定@version
后缀来安装特定版本的可执行文件。
go install golang.org/x/tools/gopls@v0.6.5
使用此语法时,请go install
从该确切模块版本安装命令,而忽略go.mod
当前目录和父目录中的所有文件。(不带@version
后缀,将go install
继续按原样运行,使用当前模块中列出的版本要求和替换来构建程序go.mod
。)
我们曾经建议go get -u program
安装一个可执行文件,但是这种用法与go get
中添加或更改模块版本要求的含义造成了太多混淆go.mod
。为了避免意外修改go.mod
,人们开始建议更复杂的命令,例如:
cd $HOME; GO111MODULE=on go get program@latest
现在我们都可以go install program@latest
代替使用。有关go install
详细信息,请参见。
为了消除关于使用哪个版本的歧义go.mod
,使用此安装语法时,程序文件中可能存在哪些指令有一些限制。特别是,至少目前不允许使用replace
和exclude
指令。从长远来看,一旦新功能go install program@version
可以在足够的用例中正常运行,我们计划go get
停止安装命令二进制文件。有关详细信息,请参见问题43684。
模块缩回
您是否曾经在准备就绪之前意外发布了模块版本?还是在发布需要快速修复的版本后立即发现问题?发布版本中的错误很难纠正。为了保持模块构建的确定性,发布版本后不能对其进行修改。即使您删除或更改了版本标签,proxy.golang.org
其他代理也可能已经缓存了原始代理。
现在,模块作者可以使用中的指令撤消模块版本。缩回的版本仍然存在并且可以下载(因此依赖它的版本不会中断),但是在解析诸如的版本时,该命令不会自动选择它。 并且,将打印现有用途的警告。retract
go.mod
go
@latest
go get
go list -m -u
例如,假设一个流行的库的example.com/lib
发行人发行v1.0.5
,然后发现一个新的安全问题。他们可以将指令添加到其go.mod
文件中,如下所示:
// Remote-triggered crash in package foo. See CVE-2021-01234.
retract v1.0.5
接下来,作者可以标记并推送v1.0.6
新的最高版本version。此后,v1.0.5
当检查更新或升级从属程序包时,已经通知已依赖的用户将撤消通知。通知消息可能包含retract
指令上方注释中的文本。
$ go list -m -u all
example.com/lib v1.0.0 (retracted)
$ go get .
go: warning: example.com/lib@v1.0.5: retracted by module author:
Remote-triggered crash in package foo. See CVE-2021-01234.
go: to switch to the latest unretracted version, run:
go get example.com/lib@latest
有关基于浏览器的交互式指南,请在play-with-go.dev上查看“收回模块版本” 。有关语法的详细信息,请参见指令文档。retract
使用GOVCS控制版本控制工具
该go
命令可以从像一面镜子下载模块的源代码proxy.golang.org或直接从一个版本控制库使用git
,hg
,svn
,bzr
,或fossil
。直接版本控制访问非常重要,尤其是对于代理中不可用的私有模块而言,但这也可能是安全问题:版本控制工具中的错误可能被恶意服务器利用以运行意外的代码。
Go 1.16引入了一个新的配置变量,GOVCS
它使用户可以指定允许哪些模块使用特定的版本控制工具。 GOVCS
接受以逗号分隔的pattern:vcslist
规则列表。的pattern
是一个path.Match
模式匹配的一个或一个模块路径的更主导的元件。特殊模式public
与private
匹配的公共模块和私有模块(private
被定义为由模式匹配的模块GOPRIVATE
;public
其他所有内容)。的vcslist
是允许的版本控制命令或关键字的管子分隔的列表all
或off
。
例如:
GOVCS=github.com:git,evil.com:off,*:git|hg
通过此设置,github.com
可以使用来下载打开了路径的模块git
。evil.com
无法使用任何版本控制命令下载上的路径,并且*
可以使用git
或下载其他所有路径(匹配所有内容)hg
。
如果GOVCS
未设置,或者模块与任何模式都不匹配,则该go
命令使用以下默认值:git
和hg
允许用于公共模块,并且允许使用所有工具用于私有模块。仅允许使用Git和Mercurial的原因是,这两个系统最关注作为不受信任服务器的客户端运行的问题。相反,Bazaar,Fossil和Subversion主要用于受信任的,经过身份验证的环境,并且没有像攻击面那样受到严格的审查。即,默认设置为:
GOVCS=public:git|hg,private:all
有关更多详细信息,请参见控制版本控制工具GOVCS
。
下一步是什么?
我们希望您发现这些功能有用。我们已经在努力开发Go 1.17的下一组模块功能,尤其是延迟模块加载,这应该使模块加载过程更快,更稳定。与往常一样,如果您遇到新的错误,请在问题跟踪器上告知我们。祝您编码愉快!