为了账号安全,请及时绑定邮箱和手机立即绑定

不一致的错误:换行 / 错误 - 展开 / fmt.Errorf(%w)

不一致的错误:换行 / 错误 - 展开 / fmt.Errorf(%w)

Go
一只萌萌小番薯 2022-10-24 08:58:28
fmt.Errorf使用with%w和 using包装错误之间似乎存在不一致errors.Wrap:    e1 := errors.New("error1")    efmt := fmt.Errorf("error2: %w", e1)    eerr := errors.Wrap(e1, "error2")    fmt.Println(errors.Unwrap(efmt))       // error1    fmt.Println(errors.Unwrap(efmt) == e1) // true    fmt.Println(errors.Unwrap(eerr))       // error2: error1    fmt.Println(errors.Unwrap(eerr) == e1) // false :-(此处提供了完整示例我不确定这是否是有意的,但这似乎不一致......有什么理由吗?这在任何地方都有记录吗?
查看完整描述

1 回答

?
繁华开满天机

TA贡献1816条经验 获得超4个赞

这是预期的工作,这不违反文档。多个错误可能包含在单个error值中,并且由于调用Unwrap()返回单个错误,显然没有得到您期望的内容并不意味着没有包含预期的错误。


该errors软件包来自标准库。它没有errors.Wrap()功能。您使用的是 from github.com/pkg/errors.Wrap(),它在引擎盖下进行“双重包装”。


首先它用给定的错误消息包装错误,然后再次包装以保留堆栈信息:


// Wrap returns an error annotating err with a stack trace

// at the point Wrap is called, and the supplied message.

// If err is nil, Wrap returns nil.

func Wrap(err error, message string) error {

    if err == nil {

        return nil

    }

    err = &withMessage{

        cause: err,

        msg:   message,

    }

    return &withStack{

        err,

        callers(),

    }

}

当您调用时Unwrap(),将返回来自第二次包装的错误(这不是原始错误,而是包装原始错误的包装错误),Unwrap()再次调用将返回原始错误。


fmt.Println("Double unwrap:",

    errors.Unwrap(errors.Unwrap(err2wrp)) == err1)

这就是为什么你应该使用errors.Is()来避免这种“怪癖”:


fmt.Println("Proper use:", errors.Is(err2wrp, err1))

在Go Playground上试试这些。

请注意,以上报告true是您调用github.com/pkg/errors.Is()还是标准库的errors.Is().


查看完整回答
反对 回复 2022-10-24
  • 1 回答
  • 0 关注
  • 80 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号