go从0到1项目实战体系十六:go errors

2023-12-24 06:13:38

1. 创建一个被包装的 error:

(1). fmt.Errorf:

. 使用%w参数返回一个被包装的error.. 举例:
    err1 := errors.New("new error")
    err2 := fmt.Errorf("err2: [%w]", err1)     // 一个合法的被包装的error
    err3 := fmt.Errorf("err3: [%w]", err2)
    fmt.Println(err3)      // output err3: [err2: [new error]]

(2). 自定义struct:

. fmt/errors.go中关于warp的结构.. 举例:
	type WarpError struct {
		msg string
		err error
	}
	func (e *WarpError) Error() string {
		return e.msg
	}
	// 自定义一个实现了Unwrap方法的struct就可以了
	func (e *WrapError) Unwrap() error {
		return e.err
	}

2. 拆开一个被包装的error:

errors.Unwrap
err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)
fmt.Println(errors.Unwrap(err3))
fmt.Println(errors.Unwrap(errors.Unwrap(err3)))

// output
err2: [new error]
new error

3. 判断被包装的error是否是包含指定错误:

errors.Is
当多层调用返回的错误被一次次地包装起来,我们在调用链上游拿到的错误如何判断是否是底层的某个错误呢?
它递归调用 Unwrap 并判断每一层的 err 是否相等,如果有任何一层 err 和传入的目标错误相等,则返回 trueerr1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)

fmt.Println(errors.Is(err3, err2))
fmt.Println(errors.Is(err3, err1))
// output
true
true

4. 提取指定类型的错误:

errors.As
这个和上面的 errors.Is 大体上是一样的,区别在于 Is 是严格判断相等,即两个 error 是否相等。
而 As 则是判断类型是否相同,并提取第一个符合目标类型的错误,用来统一处理某一类错误。

type ErrorString struct {
    s string
}

func (e *ErrorString) Error() string {
    return e.s
}

var targetErr *ErrorString
err := fmt.Errorf("new error:[%w]", &ErrorString{s:"target err"})
fmt.Println(errors.As(err, &targetErr))
// output
true
扩展
Is As 两个方法已经预留了口子,可以由自定义的 error struct 实现并覆盖调用。

文章来源:https://blog.csdn.net/m0_68635815/article/details/135177014
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。