日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Go 分布式学习利器(14)-- Go语言的错误处理

發(fā)布時(shí)間:2023/11/27 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 分布式学习利器(14)-- Go语言的错误处理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. Go 的錯(cuò)誤機(jī)制

Go 語言的錯(cuò)誤機(jī)制中與其他語言的主要差異如下:

  • 沒有異常機(jī)制
  • error 類型實(shí)現(xiàn)了 error接口
    type error interface {Error() string
    }
    
  • 可以通過errors.New來快速創(chuàng)建錯(cuò)誤實(shí)例
    errors.New(" num is not in range[0,100]")
    

如下測(cè)試代碼演示基本的錯(cuò)誤處理:

package error_testimport ("errors""testing"
)/* 斐波那契數(shù)列 */
func GetFibList(n int) ([]int,error){ // 兩個(gè)返回值if n < 2 || n > 100 { // 返回錯(cuò)誤return nil, errors.New("n should in range [2..100]")}fibList := []int{1,1}for i := 2; i < n; i++ {fibList = append(fibList, fibList[i-1] + fibList[i-2])}return fibList,nil
}func TestFibArray(t *testing.T) {if v,err := GetFibList(-10);err != nil {t.Error(err)} else {t.Log(v)}
}

輸出如下:

=== RUN   TestFibArrayerror_test.go:24: n should in range [2..100]
--- FAIL: TestFibArray (0.00s)

如果我們需要有多種錯(cuò)誤類型的返回,那么就需要區(qū)分不同的錯(cuò)誤,可以通過設(shè)置預(yù)置的錯(cuò)誤類型來 快速簡(jiǎn)便得區(qū)分不同的錯(cuò)誤

package error_testimport ("errors""testing"
)/*區(qū)分不同的錯(cuò)誤類型*/
var LessThanTwo = errors.New("n should large than 2")
var BiggerThanHundred = errors.New("n should small than 100")/* 斐波那契數(shù)列 */
func GetFibList(n int) ([]int,error){ /* 兩個(gè)返回值 */if n < 2 {return nil, LessThanTwo}if n > 100 {return nil, BiggerThanHundred}fibList := []int{1,1}for i := 2; i < n; i++ {fibList = append(fibList, fibList[i-1] + fibList[i-2])}return fibList,nil
}func TestFibArray(t *testing.T) {if v,err := GetFibList(-10);err != nil {t.Error(err)} else {t.Log(v)}
}

輸出如下:

=== RUN   TestFibArrayerror_test.go:32: n should large than 2
--- FAIL: TestFibArray (0.00s)

2. 錯(cuò)誤處理的最佳實(shí)踐

按照我們以上代碼的處理邏輯,我們能夠發(fā)現(xiàn)函數(shù)有多個(gè)返回值的時(shí)候 如果每個(gè)返回值都需要判斷,并作出對(duì)應(yīng)的錯(cuò)誤處理,這回讓代碼非常冗余。
所以一般針對(duì)有多個(gè)錯(cuò)誤 返回值的多個(gè)函數(shù),會(huì)直接判斷錯(cuò)誤返回值不為空,直到調(diào)用到最終正常的結(jié)果才返回。

如下函數(shù)針對(duì)多個(gè)函數(shù)的多個(gè)錯(cuò)誤返回值的正常處理:

func GetFibList2( str string) {var (i interr errorlist []int)if i, err = strconv.Atoi(str); err != nil { // 錯(cuò)誤輸出fmt.Println("Atoi error", err)return}if list,err = GetFibList(i); err != nil{ // 錯(cuò)誤輸出fmt.Println("GetFibList error",err)return}fmt.Println(list) // 直到所有函數(shù)都執(zhí)行正常才最終輸出
}

3. panic和recover

panic關(guān)鍵字是Go語言中程序異常退出的關(guān)鍵字

  • 用于不可以恢復(fù)的錯(cuò)誤
  • panic 程序退出前 會(huì)執(zhí)行 defer指定的函數(shù),并打印函數(shù)調(diào)用棧

這里先對(duì)比一下panicos.Exit 兩個(gè)異常退出函數(shù)的區(qū)別

  • os.Exit 退出時(shí)不會(huì)調(diào)用defer函數(shù)
  • os.Exit 退出時(shí)不會(huì)打印函數(shù)調(diào)用棧信息

如下測(cè)試代碼:

package errorimport ("errors""fmt""testing"
)func TestPanicVsExit(t *testing.T){defer func(){fmt.Println("finally execute")}()fmt.Println("start")//	os.Exit(-1)panic(errors.New("something wrong"))
}

輸出如下,可以看到panic能夠打印調(diào)用棧和執(zhí)行defer函數(shù)

=== RUN   TestPanicVsExit
start
finally execute
--- FAIL: TestPanicVsExit (0.00s)
panic: something wrong [recovered]panic: something wronggoroutine 18 [running]:
testing.tRunner.func1.1(0x11199c0, 0xc00008e4a0)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:988 +0x30d
testing.tRunner.func1(0xc0000ce120)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:991 +0x3f9
panic(0x11199c0, 0xc00008e4a0)/usr/local/Cellar/go/1.14.6/libexec/src/runtime/panic.go:969 +0x166
command-line-arguments.TestPanicVsExit(0xc0000ce120)/Users/zhanghuigui/go/src/test/ch10/error_test/panic_test.go:17 +0xd7
testing.tRunner(0xc0000ce120, 0x114b278)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:1039 +0xdc
created by testing.(*T).Run/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:1090 +0x372
FAIL    command-line-arguments  0.663s

os.Exit(-1)則直接退出程序。

recover 關(guān)鍵字類似于我們C++/Java中 的try..catch關(guān)鍵字,能夠防止程序異常后不會(huì)退出,而執(zhí)行自己想要做的異常恢復(fù)或者對(duì)應(yīng)的錯(cuò)誤處理。
Go語言通過recover完成類似其他編譯型語言的錯(cuò)誤恢復(fù)處理。
如下簡(jiǎn)單測(cè)試代碼:

package errorimport ("errors""fmt""testing"
)func TestPanicVsExit(t *testing.T){defer func(){if err := recover(); err != nil { // 并沒有做異常恢復(fù),僅僅是把異常打出來fmt.Println("recover : ", err)}}()fmt.Println("start")panic(errors.New("something wrong")) // 通過panic 傳入異常
}

最后的輸出比較有趣,可以看到panic并沒有讓程序異常退出和打程序調(diào)用棧,異常錯(cuò)誤直接被recover捕獲,程序執(zhí)行狀態(tài)是PASS

=== RUN   TestPanicVsExit
start
recover from  something wrong
--- PASS: TestPanicVsExit (0.00s)

最常見的“錯(cuò)誤恢復(fù)” 如下, 是不被建議使用的

	defer func(){if err := recover(); err != nil { // 并沒有做異常恢復(fù),僅僅是把異常打出來log.Error("recovered panic",err)}}()

這樣的處理錯(cuò)誤僅僅是把異常結(jié)果打印到日志中或者直接忽略掉,這個(gè)時(shí)候可能一些錯(cuò)誤是系統(tǒng)異常造成的,容易形成僵尸進(jìn)程。
即如果一些異常是系統(tǒng)性異常(內(nèi)存分配異常,磁盤異常。。。等),可以直接讓進(jìn)程崩潰,并將該異常告知開發(fā)者,由他決定如何處理。

總結(jié)

以上是生活随笔為你收集整理的Go 分布式学习利器(14)-- Go语言的错误处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。