init是什么
在Go语言设计过程中保留了默认的两个函数,分别是main()和init()函数。
两者的区别在于:
- main()函数只能使用于main包中,而且每个main包只能有一个main()函数
- init()函数可以使用在所有的包中,而且一个程序中可以写任意多个init()函数
:::warning
一个程序(甚至一个文件)中可以写任意多个 init() 函数,但对于维护代码可读性、排查问题并没有任何好处:::
init() 特点
init()
用于 程序运行前 的进行包初始化(自定义变量、实例化通信连接)工作- 每个包、每个程序文件 可以同时拥有多个
init()
,但不建议 - 同一个包、文件中多个 init() 执行顺序, Golang 中并未明确
- 不同包的 init()执行顺序,按照导入包的依赖关系 决定
- init() 不能被其他函数调用,而自动在main函数执行前被调用
- 我自己试了下,比如引入第三方的包,如果只是在go.mod中存在,是不会自动调用包中的init函数的,但是如果import了,则会自动执行init函数
init()什么时候执行
:::info
init()
函数 是 Golang 程序初始化 包含的一部分。
:::
在 Golang 中程序的初始化先于 main() 执行:具体由 runtime 初始化每个被导入的包。
- 初始化顺序是按照解析的依赖关系的顺序执行,没有依赖的包最先初始化。
- 首先初始化的是 每个包作用域内的常量、变量(其中:常量先于变量),之后执行包内 init()。
- 相同一个包、文件可以同时拥有多个 init()。
- init() 和 main() 一样,没有任何参数和返回值,不能够被其他函数调用。
- 同一个包、文件 多个 init() 执行顺序并未明确。
执行顺序总结: import –> const –> var –> init() –> main()
- 如果一个包导入了其他包,则首先初始化导入的包。
- 然后初始化当前包的常量。
- 接下来初始化当前包的变量。
- 最后,调用当前包的 init() 函数。
:::warning
- 只要这个包导入了,即时没有使用,也会初始化
- 一个被多个包依赖的包仅会初始化一次
:::
init 函数的用途
- 重置包级变量值
- 对包级变量的复杂初始化
- 在 init 函数中实现“注册模式
当 init 函数在检查包数据初始状态时遇到失败或错误的情况,我们该如何处理呢?
分情况而定
- 初始化失败的是必要的数据 panic处理 结束进程
- 初始化失败的是对业务没影响,可成功可失败的 输出warn或error日志 方便定位