Edited at

Goでpkg/errorsを使ってスタックトレースを残しつつエラーハンドリングもする

More than 1 year has passed since last update.

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文を使ってエラー分岐ができます。