【ヒント】Go言語で必要でない限りinit()関数の使用を避ける
By JoeVu, at: 2024年9月11日11:08
Estimated Reading Time: __READING_TIME__ minutes
GoのGoにおけるinit()関数は、main()関数よりも前、パッケージ内の他のコードよりも前に自動的に実行される特別な関数です。便利な場合もありますが、過剰に使用するとコードの追跡と保守が難しくなります。init()関数は、絶対に必要な場合以外は使用しない方が良い理由を説明します。
init()が問題となる理由
-
隠れたロジック:
init()は自動的に実行されるため、コードのメインフローからは明らかではない隠れた動作が導入される可能性があります。これは、特に大規模なプロジェクトにおいて、デバッグとコードの理解をより困難にする可能性があります。
-
実行順序: Goは、異なるパッケージ間での
init()関数の実行順序を保証しません。複数のパッケージにinit()関数がある場合、予測できない動作につながり、プログラムの推論が難しくなります。
-
複雑なテスト: 重要なセットアップロジックが
init()内に隠れている場合、テスト中にモックしたりバイパスしたりすることが困難になります。これにより、記述および保守が困難な密結合テストにつながる可能性があります。
init()を使用するタイミング
潜在的な欠点にもかかわらず、init()には正当な使用例があります。
-
パッケージレベルの設定: パッケージが使用される前に状態または設定を初期化する必要がある場合(グローバルロガーの設定など)、
init()は便利です。ただし、この設定が不可欠であり、main()または他の場所で処理できないことを確認してください。
-
コンポーネントの登録: プラグインやミドルウェアなど、拡張可能な機能を提供するパッケージの中には、コンポーネントを登録するために
init()を使用するものがあります。これは許容されますが、混乱を避けるためにこの動作を明確に文書化してください。
init()の使用例
package main
import (
"log"
"os"
)
func init() {
// グローバルロガーを設定
log.SetOutput(os.Stdout)
log.Println("Logger initialized")
}
func main() {
log.Println("This is the main function")
}
この例では、init()を使用して、main()関数が実行される前にグローバルロガーを設定しています。これは有効な使用例ですが、より明確にするために、この設定をmain()で明示的に行うことができるかどうかを検討してください。
参考資料: https://www.digitalocean.com/community/tutorials/understanding-init-in-go