Bryan

Bryan

twitter
medium

[メモ] Go initの動作

概要#

基本ルール:

  1. すべての init 関数は、1 つの Goroutine で実行されます(ただし、以下の特別な注意事項を参照してください)。
  2. パッケージ a がパッケージ b を参照している場合、a の init は b の init が完了した後に実行されます。
  3. main パッケージの main 関数は、他のすべての init 関数が実行された後に実行されます(つまり、実行順序はパッケージの init -> main の init -> main の main です)。
  4. 同じパッケージの複数のファイル内の init の実行順序は未定義であり、同じファイル内の init は上から下に実行されます。
  5. パッケージ a がパッケージ b と c の両方を参照している場合、b と c の init の順序は Go1.21 以降で定義されます。

Go1.20 以前の場合:

  1. パッケージ a がパッケージ b を参照している場合、b の init は a の前に実行されます。
  2. ただし、パッケージ a がパッケージ 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. ブロックされている場合、参照関係のないパッケージの init の完了順序は保証されません(例 c を参照)。
  3. ブロックされている場合、パッケージ a がパッケージ b に依存している場合、a の init は b の init が完了した後に開始されます(例 d を参照)。

サンプルプロジェクト#

参考#

The Go Memory Model
Go 1.21 Release Notes

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。