Goのエラーハンドリングは、他の言語(例:例外ベースのハンドリング)とは異なり、シンプルで明示的な方法が採用されています。Goではエラー処理が設計上非常に重要視されており、エラーをコード内で直接扱うのが特徴です。
以下に、Goのエラーハンドリングの仕組みと基本的な使い方を説明します。
1. エラーの返却
Goでは、多くの関数が返り値としてエラー型(error)を返します。error型は標準ライブラリに定義されており、エラーメッセージを格納します。
例:
package main
import (
"fmt"
"errors"
)
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}
func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Result:", result)
}
この例では、divide関数が成功時には計算結果とnil(エラーなし)を返し、エラー時には0とエラーメッセージを返します。
2. エラーチェック
関数を呼び出した後、返り値のエラーをチェックするのが一般的です。Goの開発者は、エラーが発生した場合に常に明示的に確認し、適切に処理することを推奨しています。
エラー処理の例:
file, err := os.Open("file.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
defer file.Close()
// ファイル操作を実行
3. エラー型(error)のカスタマイズ
Goでは、独自のエラー型を作成できます。これにより、より詳細なエラー情報を提供できます。
例:
type MyError struct {
Code int
Message string
}
func (e *MyError) Error() string {
return fmt.Sprintf("Code: %d, Message: %s", e.Code, e.Message)
}
func riskyOperation() error {
return &MyError{Code: 404, Message: "Resource not found"}
}
func main() {
err := riskyOperation()
if err != nil {
fmt.Println("Error occurred:", err)
}
}
この例では、エラー情報としてコードやメッセージを含むカスタムエラーを作成しています。
4. errors.Is と errors.As
Go 1.13以降では、エラーをラップして扱うための機能が追加されました。エラーの原因を判定したり、特定のエラー型にキャストすることができます。
例:
コードをコピーする
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("not found")
func findItem() error {
return fmt.Errorf("database error: %w", ErrNotFound)
}
func main() {
err := findItem()
if errors.Is(err, ErrNotFound) {
fmt.Println("The item was not found.")
}
}
5. ベストプラクティス
エラーの即時チェック
エラーが発生した場合、その場で処理を行いましょう。
エラーのラップ
エラーが発生した箇所を追跡するため、ラップして情報を追加するのが推奨されます。
ユーザーフレンドリーなエラーメッセージ
エラーメッセージは適切に記述し、問題解決のヒントを提供しましょう。
まとめ
Goのエラーハンドリングは明示的で、開発者にエラーのチェックと管理を促す設計となっています。このシンプルな仕組みは、コードの可読性や信頼性を向上させる助けとなります。