init函数
每个golang源文件中都可以定义一个init函数。golang系统中,所有的源文件都有自己所属的目录,每一个目录都有对应的包名。在包的引用中,一旦某一个包被使用,则这个包下边的init函数将会被执行,且只执行一次。只执行一次的含义是什么呢?
如果一个包被多个地方引用,那么只有在这个包第一次被引用时,才会执行这个包里边的init函数,其他地方对包的再次引用,这个包里边的init函数不会被执行。
下边来定义一个工程,GOPATH所在目录结构信息是:
src
---pk1
------de1.go
---pk2
------de2.go
---main.go
main.go中的内容是:
package main
import (
"pk1"
"pk2"
)
func main() {
pk1.Pk1Demo()
pk2.Pk2Demo()
}
pk1目录中的de1.go
package pk1
import (
"fmt"
)
func Pk1Demo() {
fmt.Println("pk1 demo")
}
func init() {
fmt.Println("init. package is pk1")
}
pk2目录中的de2.go
package pk2
import (
"fmt"
"pk1"
)
func Pk2Demo() {
fmt.Println("pk2 demo")
pk1.Pk1Demo()
}
func init() {
fmt.Println("init. package is pk2")
}
执行main函数,输出信息是:
init. package is pk1
init. package is pk2
pk1 demo
pk2 demo
pk1 demo
pk1包被两个地方引用,第一次引用是在pk2包中,第二次引用是在main包中。虽然pk1包被引用多次,但从程序的输出信息可知,pk1包中的init函数只执行了一次。
init 函数的作用
当我们在程序设计中,包内的变量在使用前需要进行一系列初始化操作,这些初始化操作我们又不想在使用包时手工书写,那么将这些初始化的过程放到init函数中,既能在包中变量被使用前完成了初始化,又可以对调用方屏蔽初始化繁琐过程。
init函数常见的应用是接口注册。将注册过程放到init函数中,一旦包被引用时,自动将这个包注册到指定的接口上,且由于init函数只会被执行一次,也会很好的保证不会重复的注册接口或初始化变量。