init() 函数的执行时机

553 阅读1分钟

在 Go 语言中,对于包级别的初始化来讲,首先会初始化包变量, 然后是 init() 函数(多个 init() 函数会按照文件名顺序逐个初始化)。

当包被引用的时候,执行顺序是从最深层包开始,依次往外进行初始化。

例如main.go函数导入了包A包A又导入了包B。那么初始化的执行顺序为:包B -> 包A -> main.go

下面是一个例子,mian.go导入了包A包A又导入了包B。我们定义了一个GetAGetB函数来实现包的导入关系

package main

import (
	"Study/study_init/A"
	"fmt"
)

func init() {
	fmt.Println("main函数中调用init函数")
}

func importA() {
	A.GetA()
}

func main() {
}


----- A包 -----

package A

import (
	"Study/study_init/B"
	"fmt"
)

var _ = s()

func init() {
	fmt.Println("在包A中初始化了 init 函数")
}

func GetA() {
}

func s() string {
	fmt.Println("在包A中定义变量 s")
	return "A"
}

func importB() {
	B.GetB()
}


----- B包 -----

package B

import "fmt"

var _ = s()

func init() {
	fmt.Println("在包B中初始化了 init 函数")
}

func s() string {
	fmt.Println("在包B中定义变量 s")
	return "B"
}

func GetB() {
}

结果为:

在包B中定义变量 s
在包B中初始化了 init 函数
在包A中定义变量 s
在包A中初始化了 init 函数
main函数中调用init函数

可以看见,当运行main.go的时候,先初始化了包B,然后是包A,最后是main.go。在每一个包中,是按照初始化变量->初始化init函数的顺序来初始化的。

总结

  • 如果存在包的引用,那么初始化执行顺序是从最深层包开始,依次往外进行初始化
  • 包内变量先于 init() 函数初始化
  • 一个包中可以有多个 init() 函数
  • init() 函数只会被执行一次