golang pkg/errors 如何打印自定义包装错误?

golang pkg/errors How to print custom wrapped errors?

我的项目包装了一个自定义错误类型 errNotFound,其中嵌入了一个错误。 现在我有一个 pkg/errors 包,它会生成打印调用堆栈的错误。但是,当我将此错误内联到 errNotFound 时,不会打印调用堆栈。这是一个示例,我该如何更改它?

简单:

package main

import (
    "fmt"

    stderrors "errors"
    "github.com/pkg/errors"
)

func findSomething() error {
    return errors.Errorf("something not found")
}

func main() {
    err := findSomething()
    // can print error stack
    exitf("Error1: %+v", err)

    fmt.Println()
    fmt.Println()
    // cannot print error stack
    err = ErrNotFound(err)
    exitf("Error2: %+v", err)
}

func exitf(format string, args ...interface{}) {
    fmt.Printf(format, args...)

    //os.Exit(1)
}

type errNotFound struct{ error }

func ErrNotFound(err error) error {
    if err == nil || IsErrNotFound(err) {
        return err
    }

    return errNotFound{err}
}

func IsErrNotFound(err error) bool {
    return stderrors.As(err, &errNotFound{})
}

输出:

$ go run main
Error1: something not found
main.findSomething
        /home/lianxm/github.com/play_error/main.go:11
main.main
        /home/lianxm/github.com/play_error/main.go:15
runtime.main
        /usr/local/go/src/runtime/proc.go:255
runtime.goexit
        /usr/local/go/src/runtime/asm_amd64.s:1581

Error2: something not found

我知道我可以通过err = errors.Unwrap(err)得到原始错误然后打印出来,但是这意味着我每次打印前都需要这样做,这不是很优雅的代码,我不会真的很想那样做...

这是一个示例项目:https://github.com/lianxmfor/play_error

如果您已经有了堆栈,是否有必要将错误放入另一个堆栈中?

如果是...您可以为 errNotFound 定义一个方法,例如:

func (e errNotFound) Error() string {
    return fmt.Printf("NotFound: %+v", e.err)
}

你需要用堆栈注释错误:

func ErrNotFound(err error) error {
        if err == nil || IsErrNotFound(err) {
                return err
        }

        return errors.WithStack(errNotFound{err})
}

在调用 exitf 时,您可以使用 errors.WithStack 打印堆栈跟踪。