Goベストプラクティス—エラー処理

これは、本番環境でGoを使用して数年にわたって学んだ一連のレッスンの最初の記事です。私たちは、Saltside Technologiesで本番環境で多数のGoサービスを実行しています(psst、私はバンガロールのSaltsideで複数の職を雇っています)。

大小を問わず、幅広いテーマをカバーします。

このシリーズで最初に取り上げたいテーマは、エラー処理です。多くの場合、新しいGo開発者にとって混乱と迷惑を引き起こします。

背景-エラーインターフェイス

ちょうど同じページにいます。ご存知かもしれませんが、Goのエラーは、エラーインターフェイスを実装するものにすぎません。これは、インターフェース定義がどのように見えるかです:

タイプエラーインターフェース{
    Error()文字列
}

そのため、Error()文字列メソッドを実装するものはすべてエラーとして使用できます。

エラーの確認

エラー構造体と型チェックの使用

Goを書き始めたとき、エラーメッセージの文字列比較を頻繁に行って、エラーの種類を確認しました(はい、考えるのは恥ずかしいですが、場合によっては先に進む必要があります)。

より良い方法は、エラータイプを使用することです。したがって、(もちろん)エラーインターフェイスを実装する構造体を作成し、switchステートメントで型比較を行うことができます。

エラー実装の例を次に示します。

タイプErrZeroDivision struct {
    メッセージ文字列
}
func NewErrZeroDivision(message string)* ErrZeroDivision {
    return&ErrZeroDivision {
        メッセージ:メッセージ、
    }
}
func(e * ErrZeroDivision)Error()string {
    e.messageを返す
}

これで、このエラーを次のように使用できます。

func main(){
    結果、err:= Divide(1.0、0.0)
    if err!= nil {
        switch err。(type){
        ケース* ErrZeroDivision:
            fmt.Println(err.Error())
        デフォルト:
            fmt.Println( "h *がどうなったの?")
        }
    }
    fmt.Println(結果)
}
func Divide(a、b float64)(float64、エラー){
    if b == 0.0 {
        return 0.0、NewErrZeroDivision( "ゼロで除算できません")
    }
    a / b、nilを返します
}

完全な例のGo Playリンクを次に示します。 switch err。(type)パターンに注意してください。これにより、他の何か(文字列比較など)ではなく、さまざまなエラータイプをチェックできます。

エラーパッケージと直接比較の使用

上記の方法は、エラーパッケージを使用して処理することもできます。このアプローチは、迅速なエラー表現が必要なパッケージ内のエラーチェックに推奨されます。

var errNotFound = errors.New( "アイテムが見つかりません")
func main(){
    err:= getItem(123)//これはerrNotFoundをスローします
    if err!= nil {
        スイッチエラー{
        case errNotFound:
            log.Println( "要求されたアイテムが見つかりません")
        デフォルト:
            log.Println( "不明なエラーが発生しました")
        }
    }
}

より複雑なエラーオブジェクトが必要な場合、このアプローチはあまり役に立ちません。エラーコードなど。その場合は、エラーインターフェイスを実装する独自のタイプを作成する必要があります。

即時エラー処理

時々私は以下のようなコードに出くわします(しかし、通常はもっとふわふわしています。):

func example1()エラー{
    err:= call1()
    エラーを返す
}

ここでのポイントは、エラーがすぐに処理されないことです。誰かがerr:= call1()とreturn errの間にコードを挿入することができ、意図を壊す可能性があるため、これは脆弱なアプローチです。 2つの代替アプローチ:

//戻り値とエラーを折りたたみます。
func example2()エラー{
    call1()を返します
}
//呼び出しの直後に明示的なエラー処理を行います。
func example3()エラー{
    err:= call1()
    if err!= nil {
        エラーを返す
    }
    ゼロを返す
}

上記のアプローチはどちらも私には問題ありません。彼らは同じことを達成しています。誰かがcall1()の後に何かを追加する必要がある場合、エラー処理の世話をする必要があります。

それが今日のすべてです

Goベストプラクティスに関する次の記事をお楽しみに。強くなります:)。

func main(){
    err:= readArticle( "ベストプラクティスに進む-エラー処理")
    if err!= nil {
        ping( "@ sebdah")
    }
}