網(wǎng)站首頁 編程語言 正文
正文
眾所周知golang 中recover函數(shù)可以捕捉panic,防止在出現(xiàn)異常的情況下服務(wù)整個(gè)不可用。然而某些情況下recover也無法catch panic。下面就會(huì)說一些這些情況。
一,正常情況下
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í)際上還是會(huì)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í)候才會(huì)生效。當(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會(huì)失效的情況。
- ?攜程中出現(xiàn)panic
- defer不直接調(diào)用recover
- panic的值為nil值
寫代碼的時(shí)候需要注意避免因?yàn)檫@幾種情況的出現(xiàn)而導(dǎo)致服務(wù)不可用。以上就是golang新手常遇見的一些坑。
原文鏈接:https://mp.weixin.qq.com/s/uDDJbTTLO93Z9016WB0dZA
- 上一篇:沒有了
- 下一篇:沒有了
相關(guān)推薦
- 2022-05-29 C#使用DirectX.DirectSound播放語音_C#教程
- 2022-06-30 Unity多屏幕設(shè)置的具體方案_C#教程
- 2022-05-25 <C++>深淺拷貝與初始化列表技巧你真的會(huì)了嗎
- 2022-10-29 前端圖片上傳發(fā)現(xiàn)圖片倒置解決方案 圖片鏡像效果實(shí)現(xiàn)
- 2022-11-12 超詳細(xì)解析C++實(shí)現(xiàn)快速排序算法的方法_C 語言
- 2023-01-11 Android開發(fā)中父組件調(diào)用子組件方法demo_Android
- 2022-04-24 C語言的abs()函數(shù)和div()函數(shù)你了解嗎_C 語言
- 2022-07-12 element表格 頻繁切換維度,導(dǎo)致表頭渲染有誤
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支