Go1.20 将会修改全局变量的初始化顺序。梅度二开,继续打破 Go1 兼容性承诺!

网站建设3年前发布
14 0 0

大家好,我是煎鱼。,Go1.20 已经发布了 rc1,大家都关注了一些大头的功能特性,例如:PGO、Arean 等,都没有那么的常接触到。,实质上本次新版本还修复了在全局变量初始化方面的顺序,来自《cmd/compile: global variable initialization done in unexpected order[1]》,这是个挺有趣的问题。,从案例展开,假设在同一个 package 下有 2 个文件,分别是:f1.go 和 f2.go,包含了不同的包全局变量声明和代码。,文件 f1.go。代码如下:,文件 f2.go。代码如下:,问题来了。,如果运行 go run f1.go f2.go,会输出什么结果?,运行结果如下:,你答对了吗?再仔细想想。,如果运行 go run f2.go f1.go,会输出什么结果?,运行结果如下:,这只是 run 的文件先后顺序不一样了,咋就连输出的结果都不一样了?,输出结果到底谁对谁错,还是说都错了,正确的是什么?,我们要知道正确输出的结果是什么,还得是看 Go 语言规范《The Go Programming Language Specification[2]》说了算。,2023030701452908c015a04644e847e49792137505735fbe7b9c732,sepc,在规范中的包初始化(Package initialization)章节中明确指出:"在一个包中,包级别的变量初始化是逐步进行的,每一步都会选择声明顺序中最早的变量,它不依赖于未初始化的变量。",更完整和准确的阐述:,在了解了理论知识后,我们再结合官方例子看看,加强实践的补全。,例子 1。代码如下:,在初始化变量 x 之前,变量 a 和 b 会一起初始化(在同一步骤中)。,例子 2。代码如下:,初始化顺序是:d, b, c, a。,在解读了背景和规范后,再次回顾文章刚开始的案例。,文件 f1.go。代码如下:,文件 f2.go。代码如下:,第一种,运行 go run f1.go f2.go,输出:1 4 3。,第二种,运行 go run f2.go f1.go,输出:1 2 3.,如果按照规范来,分析程序变量初始化顺序和应该输出的结果。如下:,问题出在第二种情况,我们尝试改一下写法,变成如下代码:,输出结果:,预期结果就一致了。,上一个案例输出 1 2 3,这是有 BUG!与 Go 规范定义的不一致。,目前这个问题已经明确是 Go 编译/运行时的 BUG,并且这个问题已经存在了很久,将计划在 Go1.20 中修复。,不过由于不知道是否会影响用户,因此 Go 官方将会更多的关注社区反馈。,当然,这个确实是 BUG,会修。也为此认为值得打破 Go1 兼容性的原则。,今天这篇文章我们介绍了 Go 一直以来存在的一个 Go 编译/运行时的 BUG,会导致 Go 程序的全局变量会与 Go 规范本身定义的不一致,将预计会在 Go1.20 修复。,这也是 Go 打破 Go1 兼容性承诺的又一个案例。值得我们关注。

© 版权声明

相关文章