golang
中有个神奇的函数init
,该函数会在全部程序执行开始前被调用,每一个包能够包含多个init
函数,全部被编辑器识别到的init
函数都会在main
函数执行前被调用。一般被用来注册一个程序须要使用的依赖,如mysql
注册,配置文件加载等。mysql
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
函数golang
package main import ( "fmt" "test/services" ) func main() { fmt.Println("这里是main") services.Run() } func init() { fmt.Println("这里是main init") }
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
的顺序是怎么样的。sql
在上面的基础上增长third
包编辑器
---services -----service.go ---third -----third_a.go -----third_b.go ---main.go
package third import "fmt" func TestA() { } func init() { fmt.Println("这里是 third init a") }
package third import "fmt" func TestB() { } func init() { fmt.Println("这里是 third init b") }
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
中 包含调用便可spa