Go1.16 中模块的新变化

在前不久 Go1.16 发布了,其中模块的功能也得到了更新,来看看具体有哪些变化。

原文地址:https://blog.golang.org/go116-module-changes


我们希望你喜欢 Go1.16!这个版本中有很多的新特性,特别是在模块功能上。在发布备注中简单的描述了这些改变,现在让我们来深入的研究一下。

模块的默认设置

现在 go 命令在编译代码时,会默认使用启用模块功能,即使没有 go.mod 文件。这促进了在所有的项目中使用模块功能。

如果把 GO111MODULE 设置为 off,就还可以在 GOPATH 下编译代码。也可以把 GO111MODULE 设置为 auto,这样就可以检测当前目录或者父目录中的 go.mod 文件。你可以使用 go env -w 来设置 GO111MODULE 或者其他变量的值:

$ go env -w GO111MODULE=auto

我们计划在 Go1.17 中放弃对 GOPATH 的支持,换句话说,在 Go1.17 中,将会忽略 GO111MODULE 变量。如果你还有项目没有使用 Go Modules,现在是时候迁移了。如果在迁移的过程中,如果你遇到了问题,可以提交一个 issue 或者一个体验报告。

不自动修改 go.mod 和 go.sum

在之前,当 go 命令发现 go.mod 或者 go.sum 缺少了 require 命令或者缺少一个检验和,它会尝试自动去修复这个问题。我们收到了很多反馈,表示这种行为会让人意外,特别是还有 go list 这种本不该有副作用的命令。这种自动修复通常补充很准确,如果导入的包在依赖中找不到,go 命令就会添加一个新的依赖,可能会触发对其他依赖的升级。甚至一个拼写错误的导入路径都会触发一个失败的网络依赖查询。

在 Go1.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 目录(请参阅 vendor 获取更多信息)。像 go get 和 go mod tidy 命令任然可以修改 go.mod 和 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 来安装依赖包,但 go get 命令会在 go.mod 中增加或者修改模块的依赖版本,会让人迷惑。为了避免这种意外的修改,有人开始使用下面这种复杂的命令:

$ cd $HOME; GO111MODULE=on go get program@latest

现在我们可以用 go install program@latest 来进行安装。在 go install 查看详情。

为了避免对使用哪个版本出现歧义,在使用 go install 命令时,在 go.mod 中设置了几个限制。特别是暂时不允许使用 replace 和 exclude。如果后续 go install program@version 的表现足够好,我们计划让 go get 不再用来安装程序。具体参见 issue 43684

模块撤销

你曾经有没有发布过没有准备好的版本?或者你在发布一个版本后发现了一个问题,需要快速修复?在发布的版本中修复错误通常很困难。为了保持模块构建的确定性,一个版本在发布后不能被修改。如果你删除或者修改版本的 tag,但在 proxy.golang.org 或者其他代理商可能已经有了原版本的缓存。

模块的作者现在可以在 go.mod 中使用 retract 撤回某个版本。一个被撤回的版本还会存在,也可以下载(依赖这个版本的程序不会崩溃),但是在使用 @latest 来下载依赖时,go 命令不会自动去选择这个被撤回的版本。对于已经在用这个版本程序,执行 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

接下来,作者打了一个新的 tag 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/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 上的模块版本撤回。更多详细语法参见

使用 GOVCS

go 命令可以通过代理镜像(比如:proxy.golang.org)或者通过版本控制仓库(git、hg、svn、bzr、fossil 等等)下载源码。直接的版本控制访问很重要,特别是对于在代理上不可用的私有模块,但它也是一个潜在的安全问题,版本控制工具中的漏洞可能被恶意服务器利用来运行非预期的代码。

Go1.16 中新增了一个配置变量,GOVCS,可以让用户指定允许的版本控制工具。GOVCS 接受一个 pattern:vcslist 的列表,逗号隔开。pattern 是通过 path.Match 方法来匹配一个或多个模块路径的前缀。public 和 private 是两个特殊的 pattern,private 匹配私有的模块(private 匹配在 GOPRIVATE 中定义的,public 只所有可以访问模块)。vclist 是一个通过管道分隔符分割的列表,包含允许的版本控制命令或关键字 all 或 off。

比如:

GOVCS=github.com:git,evil.com:off,*:git|hg

在上面的配置中,允许通过 git 下载 github.com 上的模块。evil.com 上的所有模块都不能下载,其它的路径(*表示匹配所有)可以通过 git 或者 hg 下载。

如果 没有设置 GOVCS,或者不匹配任何路径,go 命令就会使用默认值:git 和 hg 允许用于公共模块,而私有模块允许使用所有的工具。只允许 Git 和 Mercurial 用于公共模块的原因是,这两个工具在不受信任的服务器上运行的表现最好。相比之下,Bazaar、Fossil 和 Subversion 主要是在可信任的、经过验证的环境中使用的。默认的配置如下:

GOVCS=public:git|hg,private:all

详细参见这里

接下来

我们希望这些特性对你有用。我们已经在努力的开发 Go1.17 中的新特性,特别是模块的延迟加载,这会让模块的加载更快,更稳定。另外,如果你发现了 bug,请让我们知道。Happy coding!

译 / Rayjun

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352