持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
一、init 函数:
一、基本介绍:
每一个源文件都可以包含一个init函数,该函数会在main函数执行钱,被GO运行框架调用,也就是说init会在main函数前被调用。
init 函数:函数名必须是init
作用:main 函数之前会先处理这里的内容
init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。init 函数通常被用来:
- 对变量进行初始化
- 检查/修复程序的状态
- 注册
- 运行一次计算
二、案例说明:
package main
import "fmt"
// init()函数,通常可以在init函数中完成初始化工作
func init() {
fmt.Println("init()....")
}
func main() {
fmt.Println("main()....")
}
三、细节讨论:
- 如果一个文件同时包含全局变量定义,init 函数 和 main 函数,则执行的流程是:
全局变量定义 ---> init 函数 ---> main 函数 - init 函数最主要的作用,就是完成一些初始化的工作,比如说下面的案例:
- 案例一:
package main
import "fmt"
var age = test()
// 为了看到全局变量是先被初始化的,我们这里先写函数
func test() int {
fmt.Println("test()") // 1
return 90
}
// init()函数,通常可以在init函数中完成初始化工作
func init() {
fmt.Println("init()....") // 2
}
func main() {
fmt.Println("main()....age=", age) // 3
}
- 案例二:
为了使用导入的包,首先必须将其初始化。初始化总是以单线程执行,并且按照包的依赖关系顺序执行。这通过Golang的运行时系统控制,如下图所示:
- 初始化导入的包(递归导入)
- 对包块中声明的变量进行计算和分配初始值
- 执行包中的init函数
package utils
var Age int
var Name string
// Age 和 Name 全局变量,我们需要在main.go 使用
// 但是我们需要初始化Age 和 Name
// init 函数完成初始化工作
func init() {
Age = 100
Name = "tom~"
}
package main
import (
"fmt"
// 引入包
"Program_KF/Goland_Code/chapter_06/func_init_demo_01/utils"
)
var age = test()
// 为了看到全局变量是先被初始化的,我们这里先写函数
func test() int {
fmt.Println("test()") // 1
return 90
}
// init()函数,通常可以在init函数中完成初始化工作
func init() {
fmt.Println("init()....") // 2
}
func main() {
fmt.Println("main()....age=", age) // 3
fmt.Println("Age=", utils.Age, "Name=", utils.Name)
}
utils A: 3
utils init....
utils init2....
main init3....
main全局变量初始化:3
main init.....
main init2....
main main.....
utils print....
当我们导入其他包时,会先初始化导入的包,而初始化包时,会先加载全局变量,而后从上到下加载init()函数,当被导入的包的init()函数执行完毕后,执行调用方的全局变量加载,init()函数的顺序加载,之后执行main()函数。
Go包导入规则的副作用
Go要求非常严格,不允许引用不使用的包。但是有时你引用包只是为了调用init函数去做一些初始化工作。此时空标识符(也就是下划线)的作用就是为了解决这个问题。