Perlには、コードの実行タイミングを管理するための特別なブロック(BEGIN、CHECK、INIT、END)があります:
BEGIN { ... } — ファイルのコンパイル時に即座に実行される(メインコードやモジュールの読み込み前);CHECK { ... } — すべてのファイルがコンパイルされた後、実行される前に実行される(すべてのPerlバージョンでサポートされているわけではない);INIT { ... } — メインコードの実行前に実行される("runtime");END { ... } — プログラムが終了した後、スクリプトから退出する際に実行される。実行の順序は次のとおりです:
BEGINCHECKINITEND例:
BEGIN { print "BEGIN executed "; } CHECK { print "CHECK executed "; } INIT { print "INIT executed "; } print "Main code executed "; END { print "END executed "; }
モジュール内のBEGINブロックは、requireを使用してそのモジュールをインポートした場合、プログラムのグローバル状態に影響を与えることがありますか?
回答と例:
BEGINブロックはコンパイル時に実行されるため、モジュールがrequireを使用してインポートされた場合(実行時にインポートされる)、実行されません。useの場合(呼び出しファイルのコンパイル中に実行される)とは異なります。これにより、BEGINに依存する初期化が不安定な動作を引き起こす可能性があります。
物語 1: あるプロジェクトでは、環境変数の初期化に
BEGINが使用されており、モジュールはrequireを使用してインポートされていました。その結果、変数は設定されず、本番環境での設定の読み込みに混乱を招きました。
物語 2: ファイルディスクリプタを閉じるために
ENDブロックを使用したが、プロセスの明示的な停止が考慮されていなかった。時々、Perlインタプリタの異常終了によりENDブロックが実行されず、ログにデータが失われることがありました。
物語 3:
CHECKブロックは環境の有効性テストを実行する唯一の場所でした。ユーザーは古いPerlバージョンでスクリプトを実行し、CHECKブロックが存在しなかったため、チェックは実行されず、重大な障害は本番環境でのみ発生しました。