https://qiita.com/yoshinori_hisakawa/items/15bf0307245744deb4fc
以下のような問題がある。この問題への回答が言語の機能としてサポートされていない。
errorから呼び出し階層を得られる保証がない
errorは単なる戻り値であるため、main関数→関数A→関数Bという呼び出しをしているとき、関数Bでerrorが発生した場合、以下のようなコードだとスタックトレースが分からない。
func main() {
result, err = A()
if err != nil {
//どういう呼び出しで発生したerrなのか分からない!
}
}
func A() (string, error) {
result, err = B();
if err != nil {
return "", err
}
return string, nil
}
func B() (string, error) {
if is成功 {
return "result", nil
} else {
return "", error.New("func B err!")
}
}それをうまく扱うためにerrorsというパッケージがあり、呼び出し階層ごとのエラーのラッピングと、そこから本来のエラーを取り出す仕組みが提供されている。
func main() {
result, err = A()
if err != nil {
fmt.Println("err info:", err) // これでスタックトレースが表示される
originalErr = errors.Cause(err) // 本来のエラーを取り出す
}
}
func A() (string, error) {
result, err = B();
if err != nil {
return "", errors.Wrap(err, "func A err!") // ラッピング
}
return string, nil
}
func B() (string, error) {
if is成功 {
return "result", nil
} else {
return "", errors.New("func B err!")
}
}
errorとしてどのような値を戻すべきか
複数種類のエラーが戻る可能性がある場合、どの種類のエラーが戻されたかを判定する方法がいくつかある。
下にいくほど、コードとしては正しいがめんどくさい。
1.「エラー値 errors.New()で作成される値」を戻す。
2.「エラー型 errorインターフェースを実装した型」を戻す。型の違いで判定する。
3.「エラー型が実装したインターフェース」の違いで判定する。エラーはerrorインターフェースと、エラー種類インターフェースを実装した型として定義。