Go の error インターフェースの基本
Go のエラーハンドリングは、他の言語でよく見る try-catch 方式とは異なる。Go では error インターフェースを返り値として扱い、呼び出し元で明示的にチェックする設計になっている。
error インターフェースの定義
error は Go の組み込みインターフェースで、非常にシンプルな構造を持つ。
type error interface {
Error() string
}Error() メソッドを実装していれば、どんな型でも error として扱える。この単純さが Go のエラーハンドリングの柔軟性を支えている。
関数からエラーを返す
Go の慣習として、エラーが発生しうる関数は最後の返り値として error を返す。
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}エラーがない場合は nil を返す。呼び出し側ではこの error が nil かどうかをチェックして処理を分岐させる。
result, err := divide(10, 0)
if err != nil {
fmt.Println("エラー:", err)
return
}
fmt.Println("結果:", result)なぜ例外ではなくエラー値なのか
Go が例外機構を採用しなかった理由はいくつかある。
例外機構
制御フローが見えにくくなる。どこで例外が発生し、どこでキャッチされるか追跡が難しい。
エラー値
エラー処理が明示的で、コードを読むだけで制御フローがわかる。
エラーを値として扱うことで、エラー処理を強制し、見落としを防ぐ効果もある。コンパイラは未使用の変数に警告を出すため、エラーを無視しにくい設計になっている。
error の nil チェック
error 型の変数が nil かどうかのチェックは、Go プログラムで最も頻出するパターンだ。
file, err := os.Open("config.json")
if err != nil {
log.Fatal(err)
}
defer file.Close()この if err != nil というイディオムは Go コードのいたるところで見かける。冗長に感じるかもしれないが、エラー処理が明示的であることの代償として受け入れられている。