NU:LOGiC Logo

【Go言語】エラーハンドリングのベストプラクティス: if err != nilパターンからカスタムエラーまで

【Go言語】エラーハンドリングのベストプラクティス: if err != nilパターンからカスタムエラーまで

基本的な if err != nil パターンから errors.As を使ったエラーの型によるチェック、そしてエラーラッピングとエラー情報の埋め込み等、基本から応用まで、Goでのエラーハンドリングのベストプラクティスを理解をコード例を添えて紹介しています!

3行で要約すると

  • Go言語のエラーハンドリングには独特のパターンがあり、それを理解することが重要です。
  • if err != nil のチェック以外にも、errors.New, fmt.Errorf, errors.As などの高度な手法があります。
  • この記事では、実用的なコード例を通じてGoでのエラーハンドリングのベストプラクティスを解説します。

基本のif err != nil パターン

Go言語で最も一般的なエラーハンドリングの方法は、if err != nil の形でエラーをチェックすることです。このシンプルな方法は、エラーが発生した場合にその場で処理を行うための基本的なステップです。

コード例

file, err := os.Open("example.txt")
if err != nil {
    log.Fatal(err)
}
// ファイル操作

出力

example.txt が存在しない場合、以下のようなエラーメッセージが出力されます。

2023/09/12 00:00:00 open example.txt: no such file or directory

log.Fatal はエラーメッセージをログに出力してプログラムを終了します。

型によるエラーチェック: errors.As

特定の種類のエラーに対してだけ特別な処理をしたい場合には、errors.As を使用してエラーの型をチェックできます。

コード例

var pathError *os.PathError
if errors.As(err, &pathError) {
    fmt.Println("Failed at path:", pathError.Path)
} else {
    fmt.Println("Generic error:", err)
}

このコードは、エラーが os.PathError の型である場合とそうでない場合で、異なるメッセージを出力します。

ラップされたエラーの取り扱い: errors.Unwraperrors.Is

Go 1.13以降で導入されたエラーラッピング機能は、エラーの文脈を保存しつつ原因となるエラーを取り出す能力を提供します。errors.Unwraperrors.Is は、エラーチェーンを遡るための便利な方法です。

コード例

ラッピングする際には fmt.Errorf%w フォーマット指定子を使用します。

// エラーをラップ
wrappedErr := fmt.Errorf("operation failed: %w", originalErr)

その後で errors.Is または errors.Unwrap を使って基底エラーを確認できます。

// エラーが特定のエラーかどうかを確認
if errors.Is(wrappedErr, originalErr) {
    fmt.Println("An original error occurred:", originalErr)
}

// エラーをアンラップ
unwrappedErr := errors.Unwrap(wrappedErr)

errors.Is は、エラーチェーンを遡り、基底エラーが originalErr と一致するかどうかを確認します。一致する場合、true を返します。

errors.Unwrap は、wrappedErr から直接的な原因であるエラー(この場合は originalErr)を取り出します。

エラー情報のリッチな埋め込み: カスタムエラータイプ

独自のエラータイプを定義することで、エラーに追加情報を埋め込むことが可能になります。これはデバッグや、特定の種類のエラーに対する高度な処理に役立ちます。

コード例

type MyError struct {
    Code    int
    Message string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code: %d, Message: %s", e.Code, e.Message)
}

このカスタムエラーを使用する例:

return &MyError{Code: 404, Message: "Not Found"}

このカスタムエラーは、Error() メソッドを持つため、Goの標準エラーとして扱うことができます。更に、エラーに CodeMessage といった追加情報を埋め込むことができます。

まとめ

Go言語には多くのエラーハンドリングの手法がありますが、最も重要なのはコードが何をしているのかを明確に理解することです。基本から高度な手法まで、エラーハンドリングはGoの美点の一つと言えるでしょう。