golang?recover函數(shù)使用中的一些坑解析
正文
眾所周知golang 中recover函數(shù)可以捕捉panic,防止在出現(xiàn)異常的情況下服務(wù)整個(gè)不可用。然而某些情況下recover也無法catch panic。下面就會說一些這些情況。
一,正常情況下
package?main
import?"fmt"
func?main(){
????defer?func(){
????????if?err?:=?recover();err?!=?nil{
????????????fmt.Printf("err?=?%v",err)
????????}
????}()
????panic("a?panic")
}
打印結(jié)果:
err?=?a?panic
Process?finished?with?exit?code?0
能正常catch panic
二, goroutine中panic
之前線上環(huán)境出現(xiàn)過接口出現(xiàn)panic導(dǎo)致服務(wù)不可用的情況,于是同事就直接在main函數(shù)加了個(gè)recover認(rèn)為萬事無憂了。實(shí)際上recover并不能捕捉到協(xié)程中的panic。
package?main
import?"fmt"
func?main(){
????defer?func(){
????????if?err?:=?recover();err?!=?nil{
????????????fmt.Printf("err?=?%v",err)
????????}
????}()
????go?func(){
????????panic("a?panic")
????}()
????select{}
}
打印結(jié)果:
panic:?a?panic
goroutine?6?[running]:
main.main.func2()
????I:/goProject/catchPanic.go:13?+0x40
created?by?main.main
????I:/goProject/catchPanic.go:12?+0x5e
實(shí)際上還是會panic導(dǎo)致服務(wù)不可用。
正確寫法
package?main
import?"fmt"
func?main(){
????go?func(){
????????defer?func(){
????????????if?err?:=?recover();err?!=?nil{
????????????????fmt.Printf("err?=?%v",err)
????????????}
????????}()
????????panic("a?panic")
????}()
????select?{}
}
返回值:
fatal?error:?all?goroutines?are?asleep?-?deadlock!
goroutine?1?[select?(no?cases)]:
main.main()
????I:/goProject/catchPanic.go:15?+0x41
err?=?a?panic
Process?finished?with?exit?code?2
可以看到panic被正常捕捉,同時(shí)因?yàn)閟elect語句陷入阻塞,報(bào)了一個(gè)死鎖的錯(cuò)。
三,間接調(diào)用recover
在我想要把recover封裝成成一個(gè)函數(shù)的時(shí)候,發(fā)現(xiàn)recover并沒有生效,因?yàn)閞ecover只有在被defer語句直接調(diào)用的時(shí)候才會生效。當(dāng)recover在其他函數(shù)內(nèi)部的時(shí)候無法正確捕捉到panic。
package?main
import?"fmt"
func?main(){
????defer?cover()
????panic("a?panic")
}
func?cover(){
????defer?func(){
????????if?err?:=?recover();err!=?nil{
????????????fmt.Println(err)
????????}
????}()
}
返回值:
panic:?a?panic
goroutine?1?[running]:
main.main()
????I:/goProject/catchPanic.go:7?+0x62
四,nil panic
panic要被捕捉,還需要滿足一種條件,就是panic不是nil panic,否則在進(jìn)行捕獲判斷的時(shí)候無法知道是panic沒有發(fā)生還是panic本身就是nil。
例如以下代碼
package?main
import?"fmt"
func?main()?{
????defer?func(){
????????if?err?:=?recover();err?!=?nil{
????????????fmt.Println(err)
????????}
????????fmt.Println("after?recover")
????}()
????panic(nil)
????select{}
}
返回值:
after?recover
recover并沒有正確處理異常,因?yàn)楫惓5闹禐閚il。
五,總結(jié)
這篇文章講述了三種recover會失效的情況。
- 攜程中出現(xiàn)panic
- defer不直接調(diào)用recover
- panic的值為nil值
寫代碼的時(shí)候需要注意避免因?yàn)檫@幾種情況的出現(xiàn)而導(dǎo)致服務(wù)不可用。以上就是golang新手常遇見的一些坑。
以上就是golang recover函數(shù)使用中的一些坑解析的詳細(xì)內(nèi)容,更多關(guān)于golang recover函數(shù)坑的資料請關(guān)注腳本之家其它相關(guān)文章!
- GO語言異常處理機(jī)制panic和recover分析
- golang?中?recover()的使用方法
- go語言異常panic和恢復(fù)recover用法實(shí)例
- go語言的panic和recover函數(shù)用法實(shí)例
- Golang中panic與recover的區(qū)別
- Go panic和recover函數(shù)使用細(xì)節(jié)深入探究
- Go中recover與panic區(qū)別詳解
- Golang Recover處理錯(cuò)誤原理解析
- Golang利用Recover進(jìn)行錯(cuò)誤處理
- go使用Cron定時(shí)實(shí)現(xiàn)recover機(jī)制
相關(guān)文章
Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn)
Go語言中的sync.RWMutex提供了讀寫鎖機(jī)制,允許多個(gè)協(xié)程并發(fā)讀取共享資源,但在寫操作時(shí)保持獨(dú)占性,本文主要介紹了Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn),感興趣的可以了解一下2025-02-02
golang gc的內(nèi)部優(yōu)化詳細(xì)介紹
Go編譯器在垃圾回收(GC)的掃描標(biāo)記階段,對存儲無指針鍵值對的map進(jìn)行了優(yōu)化,即在GC掃描時(shí)不深入掃描map內(nèi)部數(shù)據(jù),只檢查map本身是否需要回收,這一優(yōu)化顯著提升了GC掃描的速度,從而減少了GC對程序性能的影響2024-10-10

