エラーハンドリング

Go(Golang)のエラーハンドリングは、他の多くの言語と異なり、例外(exception)を使わない明示的な方式が採用されています。Goの設計理念に沿った「シンプルで予測可能な」エラーハンドリング方法について、以下に詳しく説明します。


1. Goのエラーハンドリングの基本構文

Goでは、関数の戻り値としてエラーを返すのが一般的です。関数がエラーを返す場合、通常は複数の戻り値(結果とエラー)を返します。

go
func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("division by zero") } return a / b, nil }

このようにして、エラーが発生したかどうかは error 値を通じて確認します。

呼び出し側では、以下のようにエラーをチェックします。

go
result, err := divide(10, 0) if err != nil { fmt.Println("エラー:", err) return } fmt.Println("結果:", result)

2. error型の正体

Goの標準ライブラリには、error というインターフェース型が定義されています。

go
type error interface { Error() string }

つまり、error は「Error() メソッドを持つ型」のことです。標準のエラーは errors.Newfmt.Errorf を使って簡単に作成できます。

go
err := errors.New("これはエラーです")

3. エラーのラッピングと付加情報(Go 1.13以降)

Go 1.13以降では fmt.Errorf%w フォーマットを使うことで、エラーのラッピング(入れ子構造)が可能になりました。

go
originalErr := errors.New("データベース接続失敗") wrappedErr := fmt.Errorf("ユーザの取得に失敗: %w", originalErr)

そして errors.Iserrors.As を使って、ラップされたエラーを検査できます。


4. panicrecoverの役割

Goにも例外に似たメカニズムとして panicrecover がありますが、これは通常のエラーハンドリングでは推奨されません

  • panic: プログラムの即時中断を意図して使います(例:重大なバグや制御不能な状態)。

  • recover: panic から回復するために defer の中で使います。

go
func safe() { defer func() { if r := recover(); r != nil { fmt.Println("recover:", r) } }() panic("重大なエラー発生") }

通常のビジネスロジックでは、panic ではなく error による処理が推奨されます。


5. Goのエラーハンドリングの特徴と利点

特徴 説明
明示的 戻り値を通じて常にエラーをチェック。見落としにくい。
シンプル try-catch ではなく、構文的には通常の if 文。
設計方針に一致 「明示的なコードが良いコード」(explicit > implicit) というGoの哲学に基づく。
パフォーマンス面で効率的 panic は高コストな処理なので、通常の制御フローには使用しない。

まとめ

Goのエラーハンドリングは、「戻り値で明示的にエラーを返す」という設計に基づいており、例外処理に頼らず、シンプルで堅牢なエラーチェックを可能にします。これはGoの信条である「簡潔性と明瞭性」を体現しており、大規模なシステムでも予測可能な振る舞いを実現するうえで重要な特徴の一つです。

生成日:2025/05/03