1

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,在执行的maininit。这是因为在编译的时候会先去检查导入的包,首先发现其他包里面的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中 包含调用即可

期待一起交流

qrcode_for_gh_60813539dc23_258.jpg


旧梦发癫
678 声望76 粉丝

PHP、Golang