12.5 エラーとログ出力

ログが一番活躍するのはエラーの発生時でしょう。Goの標準ライブラリにあるログの出力関数には、この用途に特化したものがいくつかあります。

log.Fatal系関数、log.Panic系関数はメッセージ出力後に呼び元に処理を返さずに終了させます。サードパーティーのログライブラリ zapzerolog も同様の関数を備えています。

しかし、Goではこのような大域脱出は基本的に推奨されません。明示的にerrorを呼び出し元に返すのがGoの基本的なエラー戦略です。しかし、上記の関数を呼ぶと、上流に処理が戻ることなく、プログラムが突然終了してしまうため、この基本原則から外れてしまいます。ログ出力関数がプロセスまで終了してしまうのは越権行為でしょう。

それでも、いくつか利用しても問題ない箇所がありますので、本節ではそれについて詳しく説明します。

12.5.1 log.Fatal()とpanic()の違い

log.Fatal()panic()log.Panic()も含む)はどちらもプログラムを終了させますが、その性格はかなり異なります。

log.Fatal()系の関数では次のような終了の仕方をします。

  • os.Exit(1)を呼び出して終了する

  • log.Fatal()で出力したメッセージ以外は出力されない

  • 呼び出し元のdeferが呼ばれることはない

  • 終了を途中で止めることはできない

たとえ、deferでOSのリソースを解放していたとしても、それが実行されることはありません。とはいえ、現代のOSであればプロセスの終了時に、OSからもらったリソースは自動的に解放されるため、仮にみなさんがMS-DOSにバイナリをエクスポートできるように改造した自作のGoコンパイラーを使っていない限りは問題ありません。ただ、ネットワーク越しになにかリクエスト送信が必要なものがあったとしたら注意が必要です。たとえばリレーショナルデータベースとの接続がある場合、うまくクローズされないとデータベースサーバー側のコネクションが枯渇して他のユーザーが利用できなくなる可能性があります。 ...