xerrors パッケージは、 独自に定義したエラー型はIsメソッドとAsメソッドでデフォルトの振る舞いを変更可能です。
Isメソッドの振る舞いを変えた例
var ErrUserNotFound1 = &ApplicationError{
code: 101,
level: "Error",
msg: "not found",
}
var ErrUserNotFound2 = &ApplicationError{
code: 101,
level: "Fatal",
msg: "not found!!!!!!",
}
type ApplicationError struct {
level string
code int
msg string
}
func (e *ApplicationError) Is(err error) bool {
var appErr *ApplicationError
return xerrors.As(err, &appErr) && e.code == appErr.code
}
func (e *ApplicationError) Error() string {
return fmt.Sprintf("%s: code=%d, msg=%s", e.level, e.code, e.msg)
}
func main() {
fmt.Printf("%v\n", xerrors.Is(ErrUserNotFound1, ErrUserNotFound2))
}
この例ではErrUserNotFound1とErrUserNotFound2のcodeは同じ 101
でlevelとmsgは異なるものを xerrors.Is
メソッドで比較しています。構造体の比較という意味では false
になるはずですが、結果は true
になります。 これは func (e *ApplicationError) Is(err error) bool
を定義し、codeだけで判定しているためです。
Asメソッド
Asメソッドも型に合わせて振る舞いを変えられますが、ユースケースが想像できませんでした。
func (e *ApplicationError) As(target interface{}) bool {
// ??
}