一文掌握Golang的panic和recover實(shí)戰(zhàn)
簡述
我們都知道在Go語言中的異常處理是通過方法返回error,然后在調(diào)用方法處接收error并處理,這里的error通常是使用在業(yè)務(wù)異常的處理。
如果程序發(fā)生數(shù)組越界、空指針等異常就不會(huì)再通過error來處理,而是通過panic直接報(bào)錯(cuò)并終止程序和打印出堆棧信息。那么如何在程序發(fā)生panic的時(shí)候去處理這個(gè)異常而不是終止程序呢?這個(gè)時(shí)候就需要使用到recover,recover可以捕獲到panic異常,并恢復(fù)程序的運(yùn)行。
panic
- 調(diào)用panic后立即終止執(zhí)行當(dāng)前函數(shù)的剩余代碼,在當(dāng)前goroutine中執(zhí)行當(dāng)前函數(shù)所有的defer
- panic只會(huì)觸發(fā)當(dāng)前goroutine的defer
recover
- 調(diào)用recover可以捕獲panic的異常,并恢復(fù)程序的執(zhí)行
- recover只在defer延遲函數(shù)中調(diào)用才會(huì)生效
實(shí)戰(zhàn)
示例1
我們首先在代碼中直接使用recover捕獲異常,并使用panic手動(dòng)拋出一個(gè)異常,看看程序會(huì)怎么樣
func main() {
test()
fmt.Println("main")
}
func test() {
if err := recover(); err != nil {
fmt.Println("recover: ", err)
}
panic("error")
}運(yùn)行上面的代碼之后可以從輸出看到在test函數(shù)中發(fā)生了panic,并且直接終止運(yùn)行,導(dǎo)致main函數(shù)中的打印也沒有生效,這是因?yàn)樵谇懊娴臅r(shí)候有講到過,recover必須在defer延遲函數(shù)中調(diào)用才會(huì)生效。
panic: error
goroutine 1 [running]:
main.test()
C:/Users/lee/GolandProjects/test/main.go:33 +0x30
main.main()
C:/Users/lee/GolandProjects/test/main.go:24 +0x13示例2
修改上面的代碼,將recover放到defer延遲函數(shù)中調(diào)用:
func main() {
test()
fmt.Println("main")
}
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recover: ", err)
}
}()
panic("error")
}這個(gè)時(shí)候我們?cè)俅芜\(yùn)行代碼,可以看到雖然在test函數(shù)中發(fā)生了panic,但是程序并沒有終止運(yùn)行,而是被defer中的recover捕獲到了異常并恢復(fù)運(yùn)行,同時(shí)main函數(shù)中的print也正常打印。
recover: error main
示例3
上面示例2中將recover是放到defer的函數(shù)中調(diào)用,那么如果在defer后面直接調(diào)用recover會(huì)生效嗎?使用下面代碼進(jìn)行測試。
func main() {
test()
fmt.Println("main")
}
func test() {
defer recover()
panic("error")
}運(yùn)行上面的代碼之后發(fā)現(xiàn)在defer后面直接調(diào)用recover是無效的,程序照樣會(huì)發(fā)生異常并終止運(yùn)行,所以**recover必須是在defer的延遲函數(shù)中調(diào)用才會(huì)生效。**示例2中是匿名延遲函數(shù),如果使用具名延遲函數(shù)同樣有效。
panic: error
goroutine 1 [running]:
main.test()
C:/Users/lee/GolandProjects/test/main.go:30 +0x58
main.main()
C:/Users/lee/GolandProjects/test/main.go:24 +0x13示例4
上面說到過recover必須在defer的延遲函數(shù)中調(diào)用,那下面的代碼可以生效嗎?
func main() {
test()
fmt.Println("main")
}
func test() {
defer func() {
defer recover()
}()
panic("error")
}運(yùn)行上面的代碼可以看到recover是生效的,recover函數(shù)被一個(gè)延遲函數(shù)調(diào)用,且recover函數(shù)本身作為一個(gè)延遲函數(shù),這個(gè)情況下也是可以正常捕獲panic異常的,程序運(yùn)行如下:
main
到此這篇關(guān)于一文掌握Golang的panic和recover的文章就介紹到這了,更多相關(guān)Golang panic和recover內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Goland 關(guān)閉自動(dòng)移除未使用的包操作
這篇文章主要介紹了Goland 關(guān)閉自動(dòng)移除未使用的包操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
用Go寫一個(gè)輕量級(jí)的ssh批量操作工具的方法
這篇文章主要介紹了用Go寫一個(gè)輕量級(jí)的ssh批量操作工具的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
基于Go編寫一個(gè)Windows剪貼板監(jiān)控器
這篇文章主要為大家詳細(xì)介紹了如何基于Go編寫一個(gè)Windows剪貼板監(jiān)控器,可以在后臺(tái)默默監(jiān)聽你的復(fù)制行為,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-11-11
Golang 定時(shí)器(Timer 和 Ticker),這篇文章就夠了
這篇文章主要介紹了Golang 定時(shí)器(Timer 和 Ticker),這篇文章就夠了,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
手把手教你如何在Goland中創(chuàng)建和運(yùn)行項(xiàng)目
歡迎來到本指南!我們將手把手地教您在Goland中如何創(chuàng)建、配置并運(yùn)行項(xiàng)目,通過簡單的步驟,您將迅速上手這款強(qiáng)大的集成開發(fā)環(huán)境(IDE),輕松實(shí)現(xiàn)您的編程夢想,讓我們一起開啟這段精彩的旅程吧!2024-02-02

