init()函数的使用

package main

import "fmt"

func main() {
   fmt.Printf("调用了main()函数,此时name=%+v \n", name)
}

func init() {
   name = "张三"
   fmt.Printf("调用了init()函数-1,此时name=%+v \n", name)
}

func init() {
   name = "李四"
   fmt.Printf("调用了init()函数-2,此时name=%+v \n", name)
}

func init() {
   name = "王五"
   fmt.Printf("调用了init()函数-3,此时name=%+v \n", name)
}

var name string

//========== 输出过程·开始 ==========//
// 调用了init()函数-1,此时name=张三
// 调用了init()函数-2,此时name=李四
// 调用了init()函数-3,此时name=王五
// 调用了main()函数,此时name=王五
//========== 输出过程·结束 ==========//

//========== 总结 ==========//
// 1、init()函数和main()函数一样都是有特定意义的保留函数,它的作用是完成一些初始化工作,任意一个.go文件都可以定义init()函数,并
//    且在一个.go文件里可以定义多个init()函数而不报redeclared错误。
// 2、init()函数会比main()函数先调用,如果一个.go文件里定义了常量和全局变量,并且定义了init()函数和main()函数,则执行顺序如下:
//    定义常量 → 定义全局变量 → 调用init()函数 → 调用main()函数  注:一个.go文件里如有多个init()函数则按定义顺序逐个调用
// 3、init()函数不能被手动调用,如果在其它函数里手动调用init()函数编译时会报“undefined: init”错误。
// 4、Go编译器会从main包开始,根据包的import情况构建出整个项目的包引用关系(树形结构),然后根据引用关系由下往上对包进行编译。由
//    于是根据包引用关系编译的原因,如果代码中存在init()函数依赖就很容易出问题,例如a.go需要使用b.go的全局变量VarB,而VarB是b.go在
//    init()函数里初始化的,也就是a.go依赖b.go的init()函数,但是由于包引用关系,a.go获取VarB时b.go的init()函数还未执行,这样程序就
//    会出问题。在大型系统中,由于包的引用关系复杂,为了避免出现init()函数依赖问题,定义了init()函数的.go文件应该自行判断是否已经执
//    行过init()函数,例如定义一个全局变量isInit(bool类型,默认为false),在init()函数里改变其值为true,这样就可以根据isInit的值判
//    断是否已经执行过init()函数,如果还未执行过init()函数就手动执行初始化操作。

Copyright © 2024 码农人生. All Rights Reserved