还能这样玩?Go 将会增强 Go1 向前兼容性

大家好,我是煎鱼。

年前我们在《醒醒吧,未来不会有 Go2 了!》文章中讨论了 Go2 的未来,明确了未来是以 Go1.x.y 为主的 Go1 时代。

为了实现这个北极星目标,Go 团队采取的策略分别是:增强 Go1 向后兼容(在前文已分享)和 Go1 向前兼容(本文重点内容)。

本次要提到的 “向前兼容”,指的是旧版本的 Go 编译新的 Go 代码。这个方向比较少被谈论,甚至特意设计。

Go1 向前兼容

Go 团队的大当家 Russ Cox,针对如下几个方面做了新设计和调整,输出了《Proposal: Extended forwards compatibility in Go》,已经得到讨论,很大概率落地。

部分重点如下:

  1. 新增 GOTOOLCHAIN 环境变量的设置。
  2. 改变在工作模块(work module)中解释 go 行的方式,增加了新的工具链(toolchain)行。
  3. 对 go get 等命令进行联动修改,允许对 GOTOOLCHAIN 和工作模块的 go 版本进行修改。

工作模块的 go.mod 和 toolchain

声明 Go 版本号

我们会在 go module 生成时,在 Go 工程下生成一个 go.mod 文件。其中会包含一个 go 行,将会声明该模块应该应用的 go 版本语义是什么版本。

如下图,声明的是 go1.13:

go.mod 文件中的 go 版本声明

在该提案落地后,本地安装的 Go 工具链如果比 go 行所声明的 go 版本新时,它将会直接提供所要求的旧语义,而不会重新下载和调用一个旧版本的 Go 工具链。

但如果 go 行声明了一个较新的 Go 工具链,那么本地安装的 Go 工具链就会下载并运行较新的工具链来满足其需求。

以下是一个例子。

在例子中,我们正在运行的版本是 go1.30。但在模块中,有一个 go.mod 声明了 go 版本:

go 1.30.1

Go1.30 会下载并调用 go1.30.1 来完成命令,因为模块中要求的 go 版本比本地安装的更高。

但如果 go.mod 文件中声明的是:

go 1.20rc1

Go1.30 将自己提供 go1.20rc1 语义,而不是运行 go1.20 rc1 工具链。因为本地安装的版本更新,可以通过 GODEBUG 来满足旧语义的诉求。

声明 Go 工具链版本号

可能会有同学想要运行更新版本的 Go 工具链,但 Go 语义上还是使用旧版本。

为了满足这点诉求,go.mod 文件也会支持 toolchain 行的设置,以此来支持新版本的工具链的使用。

如果 go.mod 文件中设置了 toolchain 行,将指定使用的工具链版本,go 行只指定语言语义的 Go 版本。

go.mod 文件如下:

go 1.18
toolchain go1.20rc1

作用是将为这个模块选择 go1.18 的语义,使用 go1.20rc1 的工具链来构建应用。

Go 工具链 GOTOOLCHAIN

将会在 Go 工具链新增 GOTOOLCHAIN 环境变量的设置和使用可以使用 go env -w 设置。也可以在 go test 时做如下调整:

GOTOOLCHAIN=go1.17.2 go test

go build 编译时可以:

GOTOOLCHAIN=go1.18rc1 go build -o myprog.exe

可能会有同学疑惑 GOTOOLCHAIN 的默认值哪来,有哪些值?

  • 设置 GOTOOLCHAIN=local:使用本地安装的 Go 工具链,不会下载不同版本的工具链。这是现在的的默认行为。
  • 设置 GOTOOLCHAIN=auto:使用工作模块的 go.mod 中声明的 go 版本(当它比本地安装的 Go 工具链要新时)。

GOTOOLCHAIN 环境变量的默认值取决于 Go 工具链。标准 Go 发行版默认为 GOTOOLCHAIN=auto,也就是将控制权交给 go.mod 文件。这是在实施这个提案后 99% 会看到的默认行为。

Go 工具链的一揽子东西里也比较多,例如:go get 命令,也会对 go.mod 文件中的 go 版本或 toolchain 行进行变更,以配合使用。

总结

在今天这篇文章中,我们介绍了 Go1 兼容性增强中的 “向前兼容” 部分,其中要点是:加大对 go.mod 文件中的 go 行和 toolchain 行和工具链 GOTOOLCHAIN 相关的应用。

核心目的是为了将 go 语法语义和 go 工具链的版本声明公开出来,达到隔离使用。再配合 “向后兼容” 中的 GODEBUG 的使用,让 Go 语言做兼容性时有更多更大的使用空间来实现机制上的保障。

这么一来,Go 语言在这一块会变得异常复杂,理解成本也会变高。希望大家后续在这块也不要再踩坑了。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

Go 图书系列

推荐阅读


煎鱼的清汤锅
今天写代码了吗 :-) 博客地址:[链接]
8.2k 声望
12.8k 粉丝
0 条评论
推荐阅读
Go1.21 速览:骚操作 panic(nil) 将成为历史!以后别这么干了。。。
大家好,我是煎鱼。在 Go 语言中,返回错误、抛出异常一直是大家比较关注的话题。在抛出异常上,我们一般都是这么用的: {代码...} 运行结果: {代码...} 这看起来一切正常,没什么问题的样子。隐晦的雷其实在现...

煎鱼阅读 170

Java8的新特性
Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java...

codecraft32阅读 27.4k评论 1

一文彻底搞懂加密、数字签名和数字证书!
微信搜索🔍「编程指北」,关注这个写干货的程序员,回复「资源」,即可获取后台开发学习路线和书籍来源:个人CS学习网站:[链接]前言这本是 2020 年一个平平无奇的周末,小北在家里刷着 B 站,看着喜欢的 up 主视...

编程指北71阅读 33.5k评论 20

Java11的新特性
Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java...

codecraft28阅读 19.3k评论 3

Java5的新特性
Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java...

codecraft13阅读 21.7k

Java9的新特性
Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java...

codecraft20阅读 15.3k

Java13的新特性
Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java...

codecraft17阅读 11.2k

8.2k 声望
12.8k 粉丝
宣传栏