一文掌握Golang的panic和recover實(shí)戰(zhàn)
簡(jiǎ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)行測(cè)試。
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 的安裝及激活教程(window、linux下安裝)
這篇文章主要介紹了Golang Goland 的安裝及激活詳細(xì)教程,包括window下安裝goland和linux下安裝goland,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10go語言實(shí)戰(zhàn)之實(shí)現(xiàn)比特幣地址校驗(yàn)步驟
這篇文章主要介紹了go語言實(shí)戰(zhàn)之實(shí)現(xiàn)比特幣地址校驗(yàn)步驟,利用生產(chǎn)的隨機(jī)數(shù)采用橢圓加密算法生成公鑰,具體步驟實(shí)例代碼請(qǐng)參考下本文2021-05-05Go?panic的三種產(chǎn)生方式細(xì)節(jié)探究
這篇文章主要介紹了Go?panic的三種產(chǎn)生方式細(xì)節(jié)探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12