go语言包管理工具Go Module在go1.16版本中更新的功能

2023-06-01 00:00:00 版本 管理工具 语言包

我们希望你享受 1.16!此版本具有很多新功能,尤其是模块。 发行说明简要描述这些变化,让我们深入探索其中一些更改。

https://golang.org/doc/go1.16


默认情况下打开 Modules

现在,go 命令在默认情况下以模块感知模式构建包,即使不存在 go.mod。

这是在所有项目中使用模块的一大步。

将 GO111MODULE 环境变量设置为 off,仍然可以在 GOPATH 模式下构建包。

您还可以将 GO111MODULE 设置为 auto,以仅在当前目录或任何父目录中存在 go.mod 文件时启用模块感知模式。

这是以前的默认设置。

请注意,您可以使用 go env-w 永久设置 GO111MODULE 和其他变量:

go env -w GO111MODULE=auto

我们计划在 1.17 中删除对 GoPath 模式的支持。

换句话说,Go 1.17 将忽略 go111module。

如果您有未在模块感知模式下构建的项目,现在是迁移的时候了。

如果遇到迁移的问题,请考虑提交问题或经验报告。


没有自动更改 Go.mod 和 go.sum

以前,当 go 命令发现 go.mod 或 go.sum 的问题, 如缺少 require 指令或缺少 sum,它将尝试自动解决问题。

 我们收到了很多反馈,认为这种行为令人惊讶,特别是对于像 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 目录,如果它存在的话(详见 Vendoring)。

像 go get 和 go mod tidy 这样的命令仍然会修改 go.mod 和 go.sum,因为它们的主要目的是为了管理依赖关系。


安装一个特定版本的可执行文件

go install 命令现在可以通过指定一个 @version 后缀来安装一个特定版本的可执行文件。

go install golang.org/x/tools/[email protected]

当使用这个语法时,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 [email protected]

现在我们都可以用 go install [email protected] 代替。详见 go install。

https://golang.org/ref/mod#go-install

为了消除关于使用哪个版本的歧义,在使用这种安装语法时,对程序的 go.mod 文件中可能出现的指令有一些限制。

特别是,"替换" 和 "排除" 指令是不允许的,至少目前是这样。

从长远来看,一旦新的 

go install [email protected]

在足够多的使用情况下运行良好,我们计划让 go get 停止安装命令二进制文件。

详情见 issue 43684。


模块撤回

你是否曾经不小心在模块准备好之前就发布了一个版本?

或者你是否在一个版本发布后马上发现了一个问题,需要迅速修复?发布的版本中的错误是很难纠正的。

为了保持模块构建的确定性,一个版本在发布后不能被修改。

即使你删除或改变了一个版本标签,proxy.golang.org 和其他代理可能已经有了原始缓存。


模块作者现在可以使用 go.mod 中的 retract 指令撤回模块版本。

被撤回的版本仍然存在并可以被下载(因此依赖于它的构建不会被破坏),但 go 命令在解析 @latest 等版本时不会自动选择它。 

go get 和 go list -m -u 将打印关于现有使用的警告。


例如,假设一个流行的库 example.com/lib 的作者发布了 v1.0.5,然后发现了一个新的安全问题。

他们可以在他们的 go.mod 文件中添加一条指令,就像下面这样。

//在软件包foo中发生远程触发的崩溃。参见CVE-2021-01234。
retract v1.0.5

接下来,作者可以标记并推送版本 v1.0.6,新的最高版本。

在这之后,已经依赖 v1.0.5 的用户在检查更新或升级依赖的软件包时,将被通知撤回的消息。

通知信息可能包括 retract 指令上面的注释文本。

go list -m -u all
example.com/lib v1.0.0 (retracted)
go get .
go: warning: example.com/[email protected]: 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/[email protected]

对于一个交互式的、基于浏览器的指南,请查看 play-with-go.dev 上的 Retract Module Versions。语法细节见 retract 指令文档。

https://golang.org/ref/mod#go-mod-file-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。

https://golang.org/ref/mod#vcs-govcs


下一步是什么?

我们希望你觉得这些功能很有用。

我们已经在为 Go 1.17 的下一组模块功能努力工作了,特别是 lazy module loading,它应该使模块加载过程更快、更稳定。

像往常一样,如果你遇到新的错误,请在问题跟踪器上告诉我们。

编码愉快!


转:

https://blog.golang.org/

相关文章