golang教學專欄為大家一起介紹Golang Recoverover 的一個小坑,希望對需要的朋友有所幫助!
1.error
#Golang被詬病非常多的一點就是缺少強大方便的異常處理機制,大部分高階程式語言,如Java、PHP、Python等都擁有一種try catch機制,這種異常捕獲機制可以非常方便的處理程序運行中可能出現的各種意外情況。 嚴格來說,在Go裡面,錯誤和異常是2種不同的類型,錯誤一般是指程序產生的邏輯錯誤,或者意料之中的意外情況,而且異常一般就是panic,比如角標越界、段錯誤。 對於錯誤,Golang採用了一個非常原始的手段,我們必須手動處理可能產生的每一個錯誤,一般會把錯誤回傳給呼叫方,下面這種寫法在Go裡面十分常見:package mainimport ( "errors" "fmt")func main() { s, err := say() if err != nil { fmt.Printf("%s\n", err.Error()) } else { fmt.Printf("%s\n", s) }}func say() (string, error) { // do something return "", errors.New("something error")}复制代码
2.panic
一般錯誤都是顯示的,程式明確回傳的,而異常往往是隱示的,不可預測的,例如下面的程式碼:package mainimport "fmt"func main() { fmt.Printf("%d\n", cal(1,2)) fmt.Printf("%d\n", cal(5,2)) fmt.Printf("%d\n", cal(5,0)) //panic: runtime error: integer pide by zero fmt.Printf("%d\n", cal(9,5))}func cal(a, b int) int { return a / b}复制代码
3.recover
雖然沒有try catch機制,Go其實有一種類似的recover機制,功能弱了點,用法很簡單:package mainimport "fmt"func main() { fmt.Printf("%d\n", cal(1, 2)) fmt.Printf("%d\n", cal(5, 2)) fmt.Printf("%d\n", cal(5, 0)) fmt.Printf("%d\n", cal(9, 2))}func cal(a, b int) int { defer func() { if err := recover(); err != nil { fmt.Printf("%s\n", err) } }() return a / b}复制代码
4.注意的坑
一般defer recover這種機制常用在常駐進程的應用,例如Web服務,在Go裡面,每一個Web請求都會分配一個goroutine去處理,在沒有做任何處理的情況下,假如某一個請求發生了panic,就會導致整個服務掛掉,這是不可接受的,所以在Web應用裡面必須使用recover保證即使某一個要求發生錯誤也不影響其它要求。 這裡我使用一小段程式碼模擬一下:package mainimport ( "fmt")func main() { requests := []int{12, 2, 3, 41, 5, 6, 1, 12, 3, 4, 2, 31} for n := range requests { go run(n) //开启多个协程 } for { select {} }}func run(num int) { //模拟请求错误 if num%5 == 0 { panic("请求出错") } fmt.Printf("%d\n", num)}复制代码
func run(num int) { defer func() { if err := recover();err != nil { fmt.Printf("%s\n", err) } }() if num%5 == 0 { panic("请求出错") } fmt.Printf("%d\n", num)}复制代码
func run(num int) { defer func() { if err := recover(); err != nil { fmt.Printf("%s\n", err) } }() if num%5 == 0 { panic("请求出错") } go myPrint(num)}func myPrint(num int) { if num%4 == 0 { panic("请求又出错了") } fmt.Printf("%d\n", num)}复制代码
理論上講,所有使用協程的地方都必須做defer recover處理,這樣才能保證你的應用萬無一失,不過開發中可以根據實際情況而定,對於一些不可能出錯的函數加了還影響性能。
Go的Web服務也是一樣,預設的recover機制只能捕獲一層,如果你在這個請求的處理中又使用了其它協程,那麼必須非常慎重,畢竟只要發生一個panic,整個Web服務就會掛掉。
最後,總結一下,Go的異常處理機制雖然沒有很多其它語言高效,但是基本上還是能滿足需求,目前官方已經在著完善這一點,Go2可能會見到。
推薦:《go語言教學#》
以上是記錄Golang Recover的一個小坑的詳細內容。更多資訊請關注PHP中文網其他相關文章!