有关Go语言的初始化(执行)顺序的问题

时间:2019-04-12 19:48:50

标签: go compilation

我是Go的新手。运行多个go文件(包括程序包,变量和init函数)时,我陷入了初始化顺序。

据我所知,有几个规则:

  1. 导入的软件包和init函数应根据其出现顺序进行调用。

  2. 如果文件A导入文件B而文件B导入文件C,则初始化顺序为C-> B-> A。

  3. 依赖关系总是首先执行。

  4. main总是最后执行。

有一个我很困惑的例子(有人告诉我初始化顺序是从小数字到大数字,例如1.1在1.2之前执行,1.2在2.1之前执行,等等)

// p1.go

package p1

import "fmt"         //1.1

var x float32 = 1.2   //1.2

func init()  {        //1.3

       fmt.Printf("p1 package, x:%f\n", x)    //1.4
}

func Donothing() {

       fmt.Println("do nothing.\n")
}

///////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ////

// a.go

package main

import "fmt"

var WhatIsThe1 = AnswerToLife(2.1) //2.1
var WhatIsThe2 = AnswerToLife(2.2) //2.2
var WhatIsThe3 = AnswerToLife(2.3) //2.3

func init() { //3.1


       fmt.Printf("init WhatIsThe in a.go `s init 3.1: %d\n", 2)

}

func init() { //3.2


       fmt.Printf("init WhatIsThe in a.go`s init 3.2: %d\n", 3)

}

///////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ////

// testinit.go

package main

import "p1" //1
import "fmt"

var WhatIsThe4 = AnswerToLife(2.4) //2.4
var WhatIsThe5 = AnswerToLife(2.5) //2.5
var WhatIsThe6 = AnswerToLife(2.6) //2.6

func AnswerToLife(index float32) float32 {

       fmt.Printf("init package level variable, WhatIsThe: %f\n", 
index)
       return index
}

func init() { //3.3

       fmt.Printf("init WhatIsThe in testinit.go`s init3.3: %d\n", 0)

}

func init() { //3.4

       fmt.Printf("init WhatIsThe in testinit.go`s init3.4: %d\n", 1)

}

func main() { //4

       p1.Donothing() //5
}

///////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ////

// z.go

package main

import "fmt"

var WhatIsThe7 = AnswerToLife(2.7) //2.7
var WhatIsThe8 = AnswerToLife(2.8) //2.8
var WhatIsThe9 = AnswerToLife(2.9) //2.9

func init() { //3.5


       fmt.Printf("init WhatIsThe in z.go`s init 3.5: %d\n", 4)

}

func init() { //3.6


       fmt.Printf("init WhatIsThe in z.go`s init 3.6: %d\n", 5)

}

我对那些事情感到困惑:

  1. 当文件声明软件包main时,可以缺少main函数吗?

  2. 如果有多个软件包main,它们之间的关系是什么?

  3. 据我从Python,Javascript等其他语言了解,应该有一个“主文件”。 Go语言怎么样?

  4. 所有软件包main(s)的初始化顺序是什么?

  5. 我对序列2.1〜2.9感到困惑,为什么要顺序执行它们而不是执行文件inita.gotestinit.go中的z.go函数?

1 个答案:

答案 0 :(得分:0)

specification说:

  

通过将单个未导入的程序包(称为主程序包)与它所导入的所有程序包可传递地链接起来,可以创建一个完整的程序。主程序包必须具有程序包名称main,并声明一个不带参数也不返回值的函数main

func main() { … }
     

通过初始化主程序包然后调用函数main开始程序执行。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。

请注意,主软件包与名称为main的软件包之间存在区别。

  1. 如果软件包文件包含主软件包,则该软件包必须具有main功能。否则,名为main的程序包中的文件不需要具有main函数。

  2. 程序的执行从上面定义的主程序包开始。其他名为main的软件包没有特殊状态。

  3. 可以有多个main软件包。只有一个软件包可以满足主软件包的要求。

  4. 程序包的初始化顺序取决于程序包之间的导入关系。任何程序包的名称在确定初始化顺序中都不起作用。