使用fmt.Errorfwith%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 :-(
一個完整的例子可以在這里找到
我不確定這是否是有意的,但這似乎不一致......有什么原因嗎?這在任何地方都有記錄嗎?
uj5u.com熱心網友回復:
這是預期的作業,這不違反檔案。多個錯誤可能被包裝在一個error值中,并且由于呼叫Unwrap()回傳一個錯誤,顯然沒有得到您期望的并不意味著預期的錯誤沒有被包裝。
該errors包來自標準庫。它沒有errors.Wrap()功能。您正在使用的是 from github.com/pkg/errors.Wrap(),它在引擎蓋下進行“雙重包裝”。
func Wrap(err error, message string) error
首先它用給定的錯誤訊息包裝錯誤,然后再次包裝以保留堆疊資訊:
// 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().
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/393687.html
