Go的錯誤機制
與其他主要編程語言的差異
- 沒有異常機制
- error類型實現了error接口
- 可以通過errors.New來快速創建錯誤實例
//error類型實現了error接口 type error interface { Error() string }
//可以通過errors.New來快速創建錯誤實例 errors.New("n must be in the range [0,10]")
最佳實踐
儘早失敗,避免嵌套!
假如結構是沒有錯誤就繼續執行另一個方法func,但func仍可能會拋出異常,則會形成嵌套的結構。
這種時候可以改寫成判斷有錯誤就拋出,並Log.
emmmmmm,這個在其他的語言應該也是很常見的方式了。
panic
panic用於不可以恢復的錯誤
panic退出前會執行defer的內容 和前面的筆記一樣,筆者是把defer當成別的語言的finnaly了,無論怎樣都會執行(大多數情況下,好像看到Java有方法可以不執行,不是很瞭解,免擡槓註釋.)
panic vs. os.Exit
os.Exit 退出時不會調用defer指定的函數的.(劃重點) (啪啪打臉 ( ̄ε(# ̄)
os.Exit 退出時不輸出當前調用棧信息
recover
defer func() { if err := recover(); err != nil { //恢復錯誤,recover會獲取拋出的err. } }() //Ps:感覺有些像Catch.
最常見的"錯誤恢復",這種方式其實是很危險的,代碼如下:
defer func() { if err := recover(); err != nil { log.Error("recoverd panic", err) } }()
當心 recover 成爲惡魔
形成殭屍服務進程,導致health check失效
"Let it Crash!"往往是我們恢復不確定性錯誤的最好方法。
就讓它崩潰,然後利用守護進程重啓.
Show the code:
關於Error
package error_test import ( "fmt" "errors" "testing" ) //區分錯誤類型,定義預置錯誤 var LessThanTwoError = errors.New("n should be not less than 2") var LagerThanHundredError = errors.New("n should be not larger than 100") func GetFibonacci(n int) ([] int, error) { if n < 2 { return nil, LessThanTwoError } if n > 100 { return nil, LagerThanHundredError } fibList := []int{1,1} for i:=2; i<n; i++{ fibList = append(fibList, fibList[i-2] + fibList[i-1]) } return fibList, nil } func TestGetFibonacci(t *testing.T){ if v,err:=GetFibonacci(-10);err != nil{ if err == LessThanTwoError { fmt.Println("Less than 2") } else if err == LagerThanHundredError { fmt.Println("Larger than 100") } }else{ t.Log(v) } }
Recover相關:
package panic_recover import ( "errors" "testing" "fmt" //"os" ) func TestPanicVxExit(t *testing.T){ defer func() { if err := recover(); err != nil { fmt.Println("recovered from ", err) } }() fmt.Println("Start") panic(errors.New("Something wrong!")) //會輸出調用棧信息,並執行defer //os.Exit(-1) //不輸出調用棧,不執行defer }