Go 1.13 errors 基本用法

Go 最新版本 1.13 中新增了 errors 的一些特性,有助於咱們更優雅的處理業務邏輯中報錯的問題。
本文主要展現 errors 包中新增方法的用法。

核心思想:套娃

啥意思呢?這玩意就像套娃同樣,從上往下扒,拿走一個還有一個,再拿走一個,誒還有一個,若是你願意,能夠一直扒到最底下沒有了爲止。shell

基本用法

1. 建立一個被包裝的 error

方式一:fmt.Errorf

使用 %w 參數返回一個被包裝的 errorcode

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

err2 就是一個合法的被包裝的 error,一樣地,err3 也是一個被包裝的 error,如此能夠一直套下去。遞歸

方式二:自定義 struct

type WarpError struct {
    msg string
    err error
}

func (e *WarpError) Error() string {
    return e.msg
}

func (e *WrapError) Unwrap() error {
    return e.err
}

以前看過源碼的同窗可能已經知道了,這就是 fmt/errors.go 中關於 warp 的結構。
就,很簡單。自定義一個實現了 Unwrap 方法的 struct 就能夠了。get

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 和傳入的目標錯誤相等,則返回 true。源碼

err1 := 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 則是判斷類型是否相同,並提取第一個符合目標類型的錯誤,用來統一處理某一類錯誤。string

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 實現並覆蓋調用。

源碼也沒什麼可說的,太簡單了,一眼就能看懂的。
相關文章
相關標籤/搜索