golang
中有个神奇的函数init
,该函数会在所有程序执行开始前被调用,每个包可以包含多个init
函数,所有被编辑器识别到的init
函数都会在main
函数执行前被调用。通常被用来注册一个程序需要使用的依赖,如mysql
注册,配置文件加载等。
在main包的使用
package main
import "fmt"
func main() {
fmt.Println("这里是mian")
}
func init() {
fmt.Println("这里是Init1")
}
func init() {
fmt.Println("这里是Init2")
}
//输出结果
这里是Init1
这里是Init2
这里是main
一个很简单的示例,可以看到init
函数是在main函数执行之前被执行的,并且一个包可以有多个init
函数
在其他包中使用
- main包
package main
import (
"fmt"
"test/services"
)
func main() {
fmt.Println("这里是main")
services.Run()
}
func init() {
fmt.Println("这里是main init")
}
- services包
package services
import "fmt"
func Run() {
fmt.Println("这里是 services run")
}
func init() {
fmt.Println("这里是 services里面的init")
}
- 结果
这里是 services里面的init
这里是main init
这里是main
这里是 services run
可以看到这里先执行了services
包里面的init
,在执行的main
的init
。这是因为在编译的时候会先去检查导入的包,首先发现其他包里面的init
,然后才会到main
包里面的init。那如果services
里面又包含了其他的包呢?其他包里面又在不同的文件中有不的init
呢?下面我们一起来看看到底init
的顺序是怎么样的。
多个包嵌套
在上面的基础上增加third
包
- 目录结构
---services
-----service.go
---third
-----third_a.go
-----third_b.go
---main.go
- third_a.go
package third
import "fmt"
func TestA() {
}
func init() {
fmt.Println("这里是 third init a")
}
- third_b.go
package third
import "fmt"
func TestB() {
}
func init() {
fmt.Println("这里是 third init b")
}
- serice.go
package services
import (
"fmt"
"test/third"
)
func Run() {
fmt.Println("这里是 services run")
third.TestB() // 先调用 testB
third.TestA() // 在调用 testA
}
func init() {
fmt.Println("这里是 services里面的init")
}
- 结果
这里是 third init a
这里是 third init b
这里是 services里面的init
这里是 main init
这里是 main
这里是 services run
可以看到这里先执行了 third_a
中的init
,再执行了third_b
中的init
,而不是按照我们函数的调用顺序来执行的,那么是按照文件的排序来定的?我觉得应该是这样的,官方只是说按源文件的顺序执行,具体是否是这样只有靠实际实践来看,目前来看是这样的顺序。其实我们大可不必纠结太多的顺序问题。
我们只需要知道,每个包中可以有多个init
函数,而其他包的init
是在main包的init
调用之前被执行,main
函数最后执行即可,如果非要有依赖的顺序关系,那么可以在init
中 包含调用即可
期待一起交流
有疑问加站长微信联系(非本文作者)