【问题标题】:golang pkg/errors How to print custom wrapped errors?golang pkg/errors 如何打印自定义包装的错误?
【发布时间】:2022-01-25 15:34:24
【问题描述】:

我的项目包含一个自定义错误类型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

【问题讨论】:

  • 也许errorNotFound 实现fmt.Formatter 可以解决这个问题,但我不知道如何实现接口????

标签: go error-handling


【解决方案1】:

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

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

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

【讨论】:

  • 是的,我需要把错误放在errNotFound中,这对我很有用,看这里:go.dev/play/p/VNJBWfbhhQZ
  • 这个方法解决了我的问题,谢谢!
【解决方案2】:

你需要用堆栈注释错误:

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

        return errors.WithStack(errNotFound{err})
}

【讨论】:

  • 是的,我能做到,谢谢!但这会打印出多个调用堆栈,我真的不想这样做。
【解决方案3】:

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

【讨论】:

  • 这与在每次exitf call 之前调用errors.Unwrap 的效果相同,我并不想这样做,它不是很优雅
猜你喜欢
  • 2022-06-11
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多