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函数 - 图1

  1. 如果一个包导入了其他包,则首先初始化导入的包。
  2. 然后初始化当前包的常量。
  3. 接下来初始化当前包的变量。
  4. 最后,调用当前包的 init() 函数。

:::warning

  • 只要这个包导入了,即时没有使用,也会初始化
  • 一个被多个包依赖的包仅会初始化一次

:::

init 函数的用途

  1. 重置包级变量值
  2. 对包级变量的复杂初始化
  3. 在 init 函数中实现“注册模式

当 init 函数在检查包数据初始状态时遇到失败或错误的情况,我们该如何处理呢?

分情况而定

  1. 初始化失败的是必要的数据 panic处理 结束进程
  2. 初始化失败的是对业务没影响,可成功可失败的 输出warn或error日志 方便定位

参考资料