当前位置: 首页 > 后端技术 > Java

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

时间:2023-04-01 21:14:03 Java

大家好,我是建宇。年前我们在《醒醒吧,未来不会有 Go2 了!》一文中讨论了Go2的未来,明确指出未来是Go1.x.y主导的Go1时代。为了实现这个NorthStar目标,Go团队采取的策略是:增强Go1的向后兼容性(前文分享)和Go1的前向兼容性(本文重点)。这次提到的“向前兼容”指的是旧版本的Go编译新的Go代码。这个方向比较少谈,甚至是故意设计的。Go1向前兼容Go团队的负责人RussCox。在以下几个方面进行了新的设计和调整。输出《Proposal: Extended forwards compatibility in Go》已经讨论过,实现概率很高。部分关键点如下:添加GOTOOLCHAIN环境变量的设置。更改了go行在工作模块中的解释方式,添加了新的工具链行。goget等命令的协同修改允许修改GOTOOLCHAIN和工作模块的go版本。工作模块的go.mod和工具链声明了Go版本号。我们在生成go模块的时候会在Go项目下生成一个go.mod文件。这将包含一个go行,该行将声明此模块应适用的go版本语义版本。如下图声明go1.13:提案实施后,如果本地安装的Go工具链比go行声明的go版本更新,则直接提供需要的旧语义,无需重新下载和调用旧版本的Go工具链。但是如果go行声明了更新的Go工具链,那么本地安装的Go工具链将下载并运行更新的工具链以满足其需要。下面是一个例子。在示例中,我们运行的是go1.30。但是在module中,有一个go.mod声明了go版本:go1.30.1Go1.30会下载并调用go1.30.1来完成命令,因为module中要求的go版本高于本地安装。但是如果go.mod文件声明:go1.20rc1Go1.30将自行提供go1.20rc1语义,而不是运行go1.20rc1工具链。因为本地安装的版本较新,旧语义的诉求可以通过GODEBUG来满足。声明Go工具链版本号可能有同学想运行更新版本的Go工具链,但是Go在语义上仍然使用旧版本。为了满足这个需求,go.mod文件也会支持toolchain行的设置,以支持使用新版本的toolchain。如果在go.mod文件中设置toolchain行,会指定使用的工具链版本,go行只指定语言语义的Go版本。go.mod文件如下:go1.18toolchaingo1.20rc1是为这个模块选择go1.18的语义,使用go1.20rc1工具链构建应用。Go工具链GOTOOLCHAIN将添加到Go工具链中设置和使用GOTOOLCHAIN环境变量,可以使用goenv-w设置。gotest时也可以做如下调整:GOTOOLCHAIN=go1.17.2gotestgobuild编译时:GOTOOLCHAIN=go1.18rc1gobuild-omyprog.exe可能有同学会疑惑GOTOOLCHAIN的默认值从何而来,是什么值在那里?设置GOTOOLCHAIN=local:使用本地安装的Go工具链,无需下载不同版本的工具链。这是现在的默认行为。设置GOTOOLCHAIN=auto:使用worker模块的go.mod中声明的go版本(当它比本地安装的Go工具链更新时)。GOTOOLCHAIN环境变量的默认值取决于Go工具链。标准的Go发行版默认为GOTOOLCHAIN=auto,它将控制权传递给go.mod文件。这是您在实施此提案后99%的时间会看到的默认行为。Gotoolchain的package里面也有很多东西,比如goget命令,也会改变go版本或者go.mod文件中的toolchain行来配合。小结在今天的文章中,我们介绍了Go1兼容性增强的“向前兼容”部分,其要点是:在go.mod文件和工具链GOTOOLCHAIN中增加go行和工具链行的使用。核心目的是暴露go的语法语义和go工具链的版本声明,实现隔离使用。再加上“向后兼容”中GODEBUG的使用,使得Go语言在做兼容的时候有了更多更大的使用空间来实现机制保障。这样一来,Go语言在这方面会变得异常复杂,理解成本也会增加。希望大家以后不要再踩这个坑了。文章持续更新中。可以微信搜索【脑补炸鱼】阅读。本文已收录在GitHubgithub.com/eddycjy/blog中。学习Go语言可以看Go学习地图和路线。欢迎星星提醒。Go书系列Go语言入门系列:初探Go项目实战Go语言编程之旅:深入使用Go做项目Go语言设计哲学:理解Go的Why与设计思维Go语言进阶之旅:进一步深入-深度围棋源码推荐阅读增加实力!Go将增强Go1的向后兼容性。兄弟们,Go1.20竞技场来了!Go十年,终于想起统一日志库!