github.com/pkg/errorsを使うと、errorオブジェクトをラップすることでスタックトレースを付加できるので便利です。
errorの中のスタックトレースは、 "%+v"
フォーマット指定で出力できます。
また、errors.Causeを使ってエラー原因を取り出すことができるので、これを利用して関数の呼び出し側からエラー原因による分岐を行うことができます。
#エラーを投げる側
package piyo
import (
"github.com/pkg/errors"
"strings"
)
var (
// エラー定義
NotFound = errors.New("not found")
UnexpectedID = errors.New("unexpected id")
)
func Find(id string) ([]Piyo, error) {
n, err := strings.Atoi(id)
if err != nil {
return nil, errors.WithStack(UnexpectedID)
}
p, err := fetch(n)
if err != nil {
return nil, errors.WithStack(NotFound)
}
return p, nil
}
#エラーを受ける側
package main
import (
"fmt"
"os"
"github.com/kaizoa/piyo"
"github.com/pkg/errors"
)
func main() {
piyos, err := piyo.Find("foo")
// エラーに応じてメッセージ変える
if err != nil {
switch errors.Cause(err) {
case piyo.NotFound:
fmt.Fprintln(os.Stderr, "Piyoはみつかりません")
case piyo.UnexpectedID:
fmt.Fprintln(os.Stderr, "PiyoのIDが間違ってます")
default:
fmt.Fprintln(os.Stderr, "不明なエラーが発生しました")
}
panic(err)
}
for _, p := range piyos {
fmt.Printf("%+v", p)
}
}
これでjavaのtry~catchのようにswitch文を使ってエラー分岐ができます。