概要#
基本ルール:
- すべての init 関数は、1 つの Goroutine で実行されます(ただし、以下の特別な注意事項を参照してください)。
- パッケージ a がパッケージ b を参照している場合、a の init は b の init が完了した後に実行されます。
- main パッケージの main 関数は、他のすべての init 関数が実行された後に実行されます(つまり、実行順序はパッケージの init -> main の init -> main の main です)。
- 同じパッケージの複数のファイル内の init の実行順序は未定義であり、同じファイル内の init は上から下に実行されます。
- パッケージ a がパッケージ b と c の両方を参照している場合、b と c の init の順序は Go1.21 以降で定義されます。
Go1.20 以前の場合:
- パッケージ a がパッケージ b を参照している場合、b の init は a の前に実行されます。
- ただし、パッケージ a がパッケージ b と c の両方を参照している場合、b と c の実行順序は定義されていません。
Go1.21 以降の場合:
- 参照関係のないパッケージ(つまり、Go1.20 以前の 2 番目のポイント)は、パッケージ名のアルファベット順に従って参照順序が決定されます(例えば、a は必ず b の前に実行されますし、github.com/xxx/xxx は必ず gitlab.com/xxx/xxx の前に実行されます)。
特別な注意:
- init がブロックされている場合、init を実行するための goroutine は新しい goroutine を作成する可能性があり、これにより一部の init コードが並行して実行される可能性があります。
- ブロックされている場合、参照関係のないパッケージの init の完了順序は保証されません(例 c を参照)。
- ブロックされている場合、パッケージ a がパッケージ b に依存している場合、a の init は b の init が完了した後に開始されます(例 d を参照)。