優雅地處理錯誤真是一門學問啊!

errors

這個你們確定使用過,標準庫的 errors 錯誤實現比較簡單,沒法進行堆棧追溯,對於產生錯誤時的上層調用者來說不是很友好,沒法得到錯誤的調用鏈詳細信息。git

// 不帶堆棧
err := errors.New("error msg")
fmt.Printf("%+v\n", err)

// 輸出
error msg

pkg/errors

github.com/pkg/errors 支持堆棧信息,能夠得到錯誤的調用鏈詳細信息。github

普通的

// 帶堆棧
err := errors.New("error msg")
fmt.Printf("%+v\n", err)

// 輸出
error msg
main.main
        /Users/xinliang/go/project/demo/err/err.go:14
runtime.main
        /usr/local/go/src/runtime/proc.go:225
runtime.goexit
        /usr/local/go/src/runtime/asm_amd64.s:1371

帶堆棧,包裝描述

err := errors.Wrap(err error, message string)

或

err := errors.Wrapf(err error, format string, args ...interface{})

帶堆棧,不包裝描述

err := errors.WithStack(err error)

不帶堆棧,包裝描述

err := errors.WithMessage(err error, message string)

或 

err := errors.WithMessagef(err error, format string, args ...interface{})

思考

你們想想,咱們在使用 pkg/errors 時,會遇到什麼問題?code

會遇到重複堆棧的問題!orm

好比,一個方法的調用鏈路比較長,就會出現這種狀況,舉個例子:get

func main() {
    err := func1()
    fmt.Printf("%+v\n", errors.Wrapf(err, "func1 error occurred"))
}

func func1() error {
    err := func2()
    return errors.Wrapf(err, "func2 error occurred")
}

func func2() error {
    err := errors.New("error msg")
    return err
}

想一想看,會打印出什麼?string

是否是發現打印出的堆棧信息有重複的?it

如何去解決這個問題?快來個人星球交流討論吧,https://t.zsxq.com/iIUVVnAasm

相關文章
相關標籤/搜索