[备忘] Go init 行为

💡 原文中文,约1000字,阅读约需3分钟。
📝

内容提要

本文讨论了Go语言中init函数的执行顺序规则。所有init函数在同一个Goroutine中执行,包的init函数在main函数之前运行。从Go1.21开始,引用关系无关的包按字母序执行,可能因阻塞导致并发执行,从而影响顺序。

🎯

关键要点

  • 所有的 init 函数都在一个 Goroutine 中执行。

  • 包的 init 函数在 main 函数之前运行。

  • 同一 package 中的多个文件中的 init 执行顺序未定义,同一文件中的 init 自上而下运行。

  • 在 Go1.21 及之后,引用关系无关的包按字母序执行。

  • 如果 init 存在阻塞,可能导致某些 init 代码并发运行,无法保证无引用关系的 package 的 init 完成先后顺序。

  • 如果 package a 依赖了 package b,那么 a 的 init 一定在 b 的 init 运行完成后开始运行。

🔎

延伸解读

Goroutine 中的 init 执行

在 Go 语言中,所有的 init 函数都在同一个 Goroutine 中执行,这意味着它们的执行是串行的。这种设计确保了在 main 函数运行之前,所有的初始化工作都已完成,避免了潜在的并发问题。开发者需要注意,虽然同一文件中的 init 函数自上而下执行,但不同文件中的 init 函数顺序是未定义的,这可能导致意外的行为。

Go 1.21 的变化

从 Go 1.21 开始,引用关系无关的包的 init 函数执行顺序将按照包名的字母序进行。这一变化可能会影响到程序的初始化顺序,尤其是在多个包之间没有直接依赖关系时。开发者在设计包时应考虑这一点,以避免因阻塞导致的并发执行问题,确保程序的稳定性和可预测性。

阻塞对 init 顺序的影响

如果 init 函数中存在阻塞操作,可能会导致某些 init 代码并发执行,从而打破无引用关系包的执行顺序。这意味着在设计 init 函数时,开发者应尽量避免长时间的阻塞操作,以确保初始化过程的顺利进行。特别是在依赖关系复杂的项目中,阻塞可能会引发难以调试的问题。

延伸问答

Go语言中的init函数执行顺序是怎样的?

所有的init函数在同一个Goroutine中执行,包的init函数在main函数之前运行。

在Go1.21之前,引用关系无关的包的init函数执行顺序是怎样的?

在Go1.20及之前,如果package a同时引用了package b和c,b和c的执行顺序是不定的。

Go1.21及之后,如何确定无引用关系的包的init执行顺序?

在Go1.21及之后,引用关系无关的包按字母序执行。

如果一个init函数存在阻塞,会有什么影响?

如果init存在阻塞,可能导致某些init代码并发运行,无法保证无引用关系的package的init完成先后顺序。

在Go语言中,如何保证依赖关系的包的init函数执行顺序?

如果package a依赖了package b,那么a的init一定在b的init运行完成后开始运行。

同一package中多个文件的init函数执行顺序是怎样的?

同一package中的多个文件的init执行顺序未定义,但同一文件中的init自上而下运行。

🏷️

标签

➡️

继续阅读