如何优化Golang中重复的错误处理
生活随笔
收集整理的這篇文章主要介紹了
如何优化Golang中重复的错误处理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在看《Go入門指南》的一種用閉包處理錯誤的模式時,里面提到了一種錯誤的優雅處理方式,減少我們重復寫if err:=f(); err != nil{}式的代碼,感覺很心動,做了下測試,結論如下:
經常的寫法
我們在設計函數時,錯誤處理要遵循以下2個規則:
我們都有這種感受,一個函數需要調用許多函數,然后處理他們的錯誤,光if err就寫了一堆,比如下面的test()函數。
package main import ("errors""log" ) func main() {test() } func test() {if err := a(); err != nil {log.Println(err)}if err := b(); err != nil {log.Println(err)}if _, err := c(1, 0); err != nil {log.Println(err)}if _, err := d(1, 0); err != nil {log.Println(err)} } func a() error {return errors.New("error in a") } func b() error {return errors.New("error in b") } func c(x, y int) (int, error) {return x + y, errors.New("error in c") } func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil }測試輸出:
2018/10/24 14:42:40 error in a 2018/10/24 14:42:40 error in b 2018/10/24 14:42:40 error in c 2018/10/24 14:42:40 error in d, divided by 0優雅的方式
借用2個小工具:
- check函數,把錯誤轉化為panic
- 函數在defer中增加錯誤處理,從panic中恢復錯誤,并打印
我們對test()函數進行小小的改造。
package main import ("errors""fmt" ) func main() {test() } func test() {defer func() {if r := recover(); r != nil {log.Println("got error: ", r)}}()var err errorerr = a()check(err)err = b()check(err)_, err = c(1, 2)check(err)_, err = d(1, 0)check(err) } func check(err error) {if err != nil {panic(err)} } func a() error {return errors.New("error in a") } func b() error {return errors.New("error in b") } func c(x, y int) (int, error) {return x + y, errors.New("error in c") } func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil }輸出結果:
2018/10/24 17:29:35 got error: error in a
test()函數是清爽了不少,也不用一直if然后處理err了,但是這種處理把錯誤轉化為panic,導致test()后續的代碼無法再繼續執行,b(), c(), d()幾個函數就沒法執行了。
所以如果test()函數,遇到錯誤后就返回,就很適合這種優雅的方式。
還可以更優雅嗎
test()函數中的defer看著挺礙眼的,我們還能讓test()更簡潔點嗎,代碼再優雅點?
采用文章中介紹的辦法,增加errorHandler()函數,實現對被調用函數的封裝,為它增加defer函數,恢復panic報的錯誤,看代碼。
package main import ("errors""log" ) func main() {errorHandler(test)() } func test() {var err errorerr = a()check(err)err = b()check(err)_, err = c(1, 2)check(err)_, err = d(1, 0)check(err) } func check(err error) {if err != nil {panic(err)} } // 封裝f:為傳入的函數增加defer func errorHandler(f func()) func() {return func() {defer func() {if r := recover(); r != nil {log.Println("got error: ", r)}}()f()} } func a() error {return errors.New("error in a") } func b() error {return errors.New("error in b") } func c(x, y int) (int, error) {return x + y, errors.New("error in c") } func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil }
結果:
2018/10/24 17:36:41 got error: error in a還能再一次優雅嗎
errorHandler()函數不夠通用,它只接受無入參,無返回的函數。
總結
以上是生活随笔為你收集整理的如何优化Golang中重复的错误处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是informer机制
- 下一篇: Kubernetes容器网络及网络模型