web-dev-qa-db-ja.com

goでエラーコードで終了しますか?

エラーコードでプログラムを終了する慣用的な方法は何ですか?

Exitのドキュメントには、「プログラムはすぐに終了します。遅延関数は実行されません。」と書かれており、_log.Fatal_はExitを呼び出します。凶悪なエラーではないものについては、遅延関数を実行せずにプログラムを終了すると極端に思えます。

エラーが発生したことを示すいくつかの状態を渡して、すべての遅延関数が実行された状態で安全に終了できることがわかっている時点でExit(1)を呼び出しますか?

39
dan

実際のmainパッケージのほとんどでこれらの行に沿って何かをするので、return err慣習はできるだけ早く採用され、適切に終了します。

func main() {
    if err := run(); err != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", err)
        os.Exit(1)
    }
}

func run() error {
    err := something()
    if err != nil {
        return err
    }
    // etc
}
54

Fasで述べたように、osパッケージのfunc Exit(exitcode int)があります。

ただし、遅延関数を適用する必要がある場合は、次のようにdeferキーワードをいつでも使用できます。

http://play.golang.org/p/U-hAS88Ug4

すべての操作を実行し、エラー変数に影響を与え、最後にすべてがクリーンアップされたら、安全に終了できます。

そうでない場合は、panic/recoverを使用することもできます。 http://play.golang.org/p/903e76GnQ-

エラーが発生すると、パニックに陥り、クリーンアップを終了して、それをキャッチ(回復)します。

3
creack

python私はよく行くパターンを次のように変換します:

func run() int {
    // here goes
    // the code

    return 1
}

func main() {
    os.Exit(run())
}
2
user2424794

これを行う最も明確な方法は、exitCodeの先頭にmainを設定し、次のステップとしてdeferを閉じることだと思います。これにより、exitCodeの任意の場所でmainを変更でき、最後の値は次のように終了します。

package main

import (
    "fmt"
    "os"
)

func main() {
    exitCode := 0
    defer func() { os.Exit(exitCode) }()

    // Do whatever, including deferring more functions

    defer func() {
        fmt.Printf("Do some cleanup\n")
    }()

    func() {
        fmt.Printf("Do some work\n")
    }()

    // But let's say something went wrong
    exitCode = 1

    // Do even more work/cleanup if you want

    // At the end, os.Exit will be called with the last value of exitCode
}

出力:

Do some work
Do some cleanup

Program exited: status 1.

遊び場に行く https://play.golang.org/p/AMUR4m_A9Dw

これの重要な欠点は、エラーコードを設定した直後にプロセスを終了しないことです。

0
Ben