Go言語でのエラーの扱い方まとめ
個人メモです。逐次更新したいですが…
基本方針
例外が起きる可能性のある関数はすべてerrorを返すようにする
go言語は複数の値を返すことができるので、エラーが起きる可能性のある関数については常にエラーをリターン値の末尾に含めるようにします
スタックトレース
スタックトレースの取得はruntime
パッケージで行うことができます
package main
import (
"fmt"
"errors"
"runtime"
)
// スタックトレースを取得する関数
func getStackTrace() string {
buf := make([]byte, 1024)
n := runtime.Stack(buf, false)
return string(buf[:n])
}
// エラーを作成する関数
func doSomething() error {
return fmt.Errorf("failed to do something: %s", getStackTrace())
}
func main() {
err := doSomething()
if err != nil {
fmt.Println("Error:", err)
}
}
エラーの判別
go1.13以降ではerror.Is
などを用いてエラーを判別できるようになっているようです。
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("not found")
func getItem(id int) (string, error) {
if id == 0 {
return "", fmt.Errorf("failed to get item: %w", ErrNotFound)
}
return "item", nil
}
func main() {
_, err := getItem(0)
if errors.Is(err, ErrNotFound) {
fmt.Println("Item not found")
}
}
エラーのraise方法
静的なエラーの場合
errors.New
で生成
import "errors"
var ErrNotFound = errors.New("not found")
func getItem(id int) (string, error) {
if id == 0 {
return "", ErrNotFound
}
return "item", nil
}
動的なエラーの場合
変数の内容などをエラーに含める場合はfmt.Errorf
で生成
import "fmt"
func getItem(id int) (string, error) {
if id == 0 {
return "", fmt.Errorf("item with id %d not found", id)
}
return "item", nil
}
エラーチェーン
呼び出し元で呼び出し先のエラー情報を利用したい場合は、fmt.Errorf
で同様にエラーをラップします
// 何らかのエラーを返す関数
func doSomething() error {
return fmt.Errorf("failed to do something")
}
// さらに上位の関数でエラーをラップする
func process() error {
err := doSomething()
if err != nil {
return fmt.Errorf("process failed: %w", err) // %w でエラーをラップ
}
return nil
}
コメント