gpt4 book ai didi

go - 带有错误的Golang错误包装/解包&&类型检查。is()

转载 作者:行者123 更新时间:2023-12-01 22:12:59 26 4
gpt4 key购买 nike

我正在通过Go v1.13 Go v1.14中的错误跟踪进行检查。为什么看起来只有errors.Is()才能找到没有参数或带有值接收器的错误实现?这意味着能够包装的错误实现必须具有一个值接收器,以便能够通过errors.Is()找到。

package main

import (
"fmt"
"errors"
)

type someAtomicError struct {}
func (e *someAtomicError) Error() string { return "Hi!" }
func checkAtomicError() {
e := &someAtomicError{}
e2 := fmt.Errorf("whoa!: %w", e)
e2IsE := errors.Is(e2, &someAtomicError{})
fmt.Println("atomic error trace ---\t\t", e2, "\t\t--- is traceable: ", e2IsE)
}


type someWrapperError struct {
Msg string
Err error
}
func (e someWrapperError) Error() string { return fmt.Sprintf("%s: %v", e.Msg, e.Err) }
func (e someWrapperError) Unwrap() error { return e.Err }
func checkWrapperError() {
e := someWrapperError{"Hi!", nil}
e2 := fmt.Errorf("whoa!: %w", e)
e2IsE := errors.Is(e2, someWrapperError{"Hi!", nil})
fmt.Println("wrapper error trace ---\t\t", e2, "\t--- is traceable: ", e2IsE)
}


type somePointerWrapperError struct {
Msg string
Err error
}
func (e *somePointerWrapperError) Error() string { return fmt.Sprintf("%s: %v", e.Msg, e.Err) }
func (e *somePointerWrapperError) Unwrap() error { return e.Err }
func checkPointerWrapperError() {
e := &somePointerWrapperError{"Hi!", nil}
e2 := fmt.Errorf("whoa!: %w", e)
e2IsE := errors.Is(e2, &somePointerWrapperError{"Hi!", nil})
fmt.Println("pointer wrapper error trace ---\t", e2, "\t--- is traceable: ", e2IsE)
}


func main() {
checkAtomicError()
checkWrapperError()
checkPointerWrapperError()
}

//atomic error trace --- whoa!: Hi! --- is traceable: true
//wrapper error trace --- whoa!: Hi!: <nil> --- is traceable: true
//pointer wrapper error trace --- whoa!: Hi!: <nil> --- is traceable: false

https://play.golang.org/p/-hSukZ-gii2

编辑:似乎参数上的任何差异,包括包装的错误参数 Err中的差异,都将导致无法通过 errors.Is()找到类型。

最佳答案

尝试通过false在另一个错误中查找一个错误时得到errors.Is的原因是-尽管两个错误可能具有相同的字段值-它们是两个不同的内存指针:

e := &somePointerWrapperError{"Hi!", nil}
ew := fmt.Errorf("whoa!: %w", e)

e2 := &somePointerWrapperError{"Hi!", nil} // e2 != e

errors.Is(ew, e2) // false - because `ew` wraps `e` not `e2`
errors.Is(ew, e) // true

因此,如何检测这种错误的“类型”并获取其值:请使用 errors.As代替:
e := &somePointerWrapperError{"Hi!", nil}
e2 := fmt.Errorf("whoa!: %w", e)

var ev *somePointerWrapperError
if errors.As(e2, &ev) {
fmt.Printf("%#v\n", ev) // &somePointerWrapperError{Msg:"Hi!", Err:error(nil)}
}

https://play.golang.org/p/CttKThLasXD

关于go - 带有错误的Golang错误包装/解包&&类型检查。is(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62441960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com