Bryan

Bryan

twitter
medium

[備忘] Go init 行為

總結#

基礎規則:

  1. 所有的 init 函數都在一個 Goroutine 中執行(但請參見下面的特殊注意)
  2. 如果 package a 引用了 package b,那麼 a 的 init 一定在 b 的 init 運行完成後運行
  3. main package 的 main 函數一定在其他 init 函數均運行完成後再運行(即運行順序為 package 的 init -> main 的 init -> main 的 main)
  4. 同一 package 中的多個文件中的 init 執行順序未定義,同一文件中的 init 自上而下運行
  5. 如果 package a 同時引用了 package b 和 c,那麼 b 與 c 的 init 順序在 Go1.21 及之後定義

在 Go1.20 及之前:

  1. 如果 package a 引用了 package b,那麼 b 的 init 一定在 a 之前運行
  2. 但是,如果 package a 同時引用了 package b 和 c,只要 b c 之間沒有引用關係,b c 的執行順序是不定的

在 Go1.21 及之後:

  1. 對於無引用關係的包(即 Go1.20 及之前的中的第 2 點),按照其包名字母序決定引用順序(例如 a 一定在 b 之前執行,github.com/xxx/xxx 一定在 gitlab.com/xxx/xxx 之前執行)

特殊注意:

  1. 如果 init 存在阻塞,那麼用於運行 init 的 goroutine 可能創建新的 goroutine,這會導致某些 init 代碼並發運行
  2. 存在阻塞的情況下,不會保證無引用關係的 package 的 init 完成先後順序(參考示例 c)
  3. 存在阻塞的情況下,如果 package a 依賴了 package b,那麼 a 的 init 一定在 b 的 init 運行完成後開始運行(參考示例 d)

示例項目#

參考#

The Go Memory Model
Go 1.21 Release Notes

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。