1. ホーム
  2. go

[解決済み] Go パッケージは log.Fatal を使うべきですか、そしてそれはいつですか?

2022-02-19 10:03:19

質問内容

これまで、私は log.Fatal が、最近偶然にもこんな質問を発見しました。 コードカバレッジ テスト使用ログ致命的 .

コードカバレッジ100問のコメントの1つにこうあります。

... 大半の場合 log.Fatal は、main関数やinit関数(あるいは、そこから直接呼び出されることを意図したいくつかの関数)でのみ使用されるべきです。

そこで、Goに付属する標準ライブラリのコードを見てみたんです。 多くの例で テスト のコードは log.Fatal というのは、問題なさそうです。 テストコード以外でも、例えば net/http 以下に示す。

// net/http/transport.go 
func (t *Transport) putIdleConn(pconn *persistConn) bool {
    ...
    for _, exist := range t.idleConn[key] {
        if exist == pconn {
            log.Fatalf("dup idle pconn %p in freelist", pconn)
        }
    }
    ...
}

を使用しないことがベストプラクティスである場合、その log.Fatal なぜ標準ライブラリで使われているのでしょうか? ライブラリの利用者にとっては os.Exit が呼び出され、アプリケーションがクリーンアップする機会を提供しません。

私の考えは甘いかもしれませんので、私の質問は、より良い実践として log.Panic その結果、私の理論上の長期安定稼働アプリケーションは、灰の中から立ち上がるチャンスを得ることができるかもしれません。

では、どのような場合にlog.Fatalを使うべきか、Goのベストプラクティスはどうなっているのでしょうか?

どのように解決するのか?

私だけかもしれませんが、私は以下のように使っています。 log.Fatal . UNIX の慣習として、エラーが発生したプロセスはできるだけ早く 0 ではない終了コードで失敗する必要があります。そのため、私は以下のようなガイドラインで log.Fatal というときに

  1. のいずれかにエラーが発生しました。 func init() これらはそれぞれ、importが処理されるとき、またはmain funcが呼ばれる前に発生するからです。逆に、私はライブラリやコマンドの行うべき作業単位に直接影響を与えないようなことだけを行います。例えば、ログの設定や、環境とパラメータが正常かどうかのチェックなどです。無効なフラグがあったらmainを実行する必要はないでしょう?そして、もし適切なフィードバックができないのであれば、それを早めに伝えるべきです。
  2. ...回復不可能なエラーが発生しました。コマンドラインで指定された画像ファイルのサムネイルを作成するプログラムがあるとします。このファイルが存在しないか、パーミッションが不十分で読めない場合、処理を続ける理由はなく、このエラーから回復することはできない。そこで、規約を守り、失敗する。
  3. ...処理中にエラーが発生し、元に戻せない可能性がある。これはちょっとソフトな定義ですね。説明しましょう。の実装があるとします。 cp そして、それは非対話的で再帰的にディレクトリをコピーするように開始されました。ここで,コピー先のディレクトリで,コピーするファイルと同じ名前(ただし内容は異なる)を持つファイルに遭遇したとする.ユーザーにどうするか決めてもらうことができず、このファイルをコピーすることができないので、問題が発生します。終了コード0で終了すると、ユーザーはコピー元とコピー先のディレクトリが完全にコピーされていると判断してしまうので、問題のファイルを単純にスキップすることはできないのです。しかし、情報を破壊する可能性があるため、単純に上書きすることもできません。これはユーザーからの明示的な要求がないと回復できない状況なので、私は log.Fatal を使用して状況を説明し、できるだけ早い段階で失敗する原則に従います。