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

Go1.20会修改全局变量的初始化顺序,两次得分并继续打破Go1兼容性承诺!

时间:2023-03-29 21:20:24 PHP

大家好,我是炸鱼。Go1.20即将发布,大家关注的主要是一些主要特性,比如:PGO、Arean等,不是那么频繁。其实这个新版本还修复了全局变量初始化的顺序,从《cmd/compile: global variable initialization done in unexpected order》开始,这是一个很有意思的问题。神奇的案例从案例开始,假设同一个包下有两个文件,分别是:f1.go和f2.go,它们包含不同的包全局变量声明和代码。文件f1.go。代码如下:packagemainvarAint=3varBint=A+1varCint=Afilef2.go。代码如下:packagemainimport"fmt"varD=f()funcf()int{A=1return1}funcmain(){fmt.Println(A,B,C)}问题来了.如果你运行gorunf1.gof2.go,输出会是什么?运行结果如下:143你答对了吗?再想一想。如果你运行gorunf2.gof1.go,输出会是什么?运行结果如下:123这只是运行中的文件顺序不同而已,为什么连输出结果都不一样呢?输出结果谁对谁错,还是都错了?什么是正确的?Go规范定义,如果我们想知道正确的输出是什么,还是要看Go语言规范《The Go Programming Language Specification》。在规范的包初始化(Packageinitialization)部分明确指出:“在一个包中,包级变量初始化是一步步进行的。每一步都会选择声明顺序最早的变量。它不取决于未初始化的变量。”一个更完整和精确的公式:如果一个包级变量还没有被初始化并且没有初始化表达式或者它的初始化表达式不依赖于未初始化的变量,那么它就被认为可以初始化了。初始化通过重复初始化声明顺序中最早且准备初始化的下一个包级变量来进行,直到没有变量准备好进行初始化。了解了理论知识之后,我们来看一下官方的例子,加强实践的完成度。示例1。代码如下:varx=avara,b=f()在变量x初始化之前,变量a和b一起初始化(在同一个步骤)。例2.代码如下:var(a=c+b//==9b=f()//==4c=f()//==5d=3//==5after初始化完成)funcf()int{d++returnd}初始化顺序为:d,b,c,a。案例的问题在哪里解读完背景和规范,再次回顾文章开头的案例。文件f1.go。代码如下:packagemainvarAint=3varBint=A+1varCint=Afilef2.go。代码如下:packagemainimport"fmt"varD=f()funcf()int{A=1return1}funcmain(){fmt.Println(A,B,C)}首先,运行gorunf1.gof2.go,output:143.第二种是rungorunf2.gof1.go,output:123.如果按照规范分析程序变量的初始化顺序和结果那应该是输出。如下:A