GO 中的 defer 有哪些注意事項(xiàng)?下
上次一起寫了 3 個案例,咱們這一次繼續(xù),這一次的會比上一次的稍微不太一樣
案例 1
還有一個也非常常用的案例,使用 defer 來捕獲異常 ,也就是當(dāng)程序崩潰的時候,defer 語句可以幫我們兜底,可以捕獲異常后按照我們期望的邏輯進(jìn)行執(zhí)行,讓程序回到正確的軌道上面
一般使程序崩潰很簡單, C/C++ 的時候,我們可以造異常,例如除 0 ,或者是數(shù)組越界等等就會導(dǎo)致程序崩潰
GO 里面造異常也可以按照上面這種方式,但是我們也可以使用 panic 函數(shù)來實(shí)現(xiàn)程序崩潰
寫一個簡單的例子,把自己的程序搞崩
func?testDefer()?{
?defer?func()?{
??fmt.Println("?panic?前?")
?}()
?panic("i?panic")?
?defer?func()?{
??fmt.Println("?panic?后")
?}()
}
func?main()?{
?testDefer()
?fmt.Println("program?over")
}
其實(shí)我們看 goland 工具就可以看到,下面這一句話是不會被執(zhí)行的
defer func() { fmt.Println(" panic 后") }()

實(shí)際運(yùn)行程序后,結(jié)果如下:

我們可以看到實(shí)際效果,程序是崩潰了,因?yàn)?fmt.Println("program over")
沒有打印出來,且看圖片,是有具體的 panic 信息的
從上述可以看明白, panic 之后的程序是不會執(zhí)行的, panic 之前的 defer 語句會執(zhí)行,因?yàn)樗热霔A?/strong>
那么我們來捕獲一下異常
還是上面的代碼,我們來捕獲一下異常,就是加一句話就可以了
func?testDefer()?{
?defer?func()?{
??fmt.Println("?panic?前?")
??if?err?:=?recover();?err?!=?nil?{
???fmt.Println("?xdm?,?我捕獲到異常了,程序不用崩潰了?")
??}
?}()
?panic("i?panic")?//觸發(fā)defer出棧
?defer?func()?{
??fmt.Println("?panic?后")
?}()
}
func?main()?{
?testDefer()
?fmt.Println("program?over")
}
看上述代碼,panic 之后的程序仍然是不會執(zhí)行的,但是我們加入了 recover() 語句, 他會幫助我們捕獲異常,處理異常

執(zhí)行上述代碼后,效果如下:
?go?run?main.go
?panic?前
?xdm?,?我捕獲到異常了,程序不用崩潰了
program?over
根據(jù)打印我們可以看出,結(jié)論和上面一個例子結(jié)論一致,并且加入異常捕獲之后,程序的崩潰堆棧信息是不會打印出來了, 并且程序是正常退出了,我們可以看到正常打印了 ?program over
案例 2
咱們再來字后一個 案例 玩一下
上面都是出現(xiàn) 1 個 panic 的情況 ,那么,如果是出現(xiàn)多個 panic 是怎么玩的呢, defer 他還能捕獲到 panic 信息嗎?若出現(xiàn) 2 個 panic, defer 也能捕獲 2 個嗎?
func?main()?{
?defer?func()?{
??if?err?:=?recover();?err?!=?nil?{
???fmt.Println("xdm,?我捕獲到異常了")
??}
?}()
?defer?func()?{
??panic("defer?func??panic")
?}()
?panic("?i?panic")
?panic("?last??panic")
?fmt.Println("baibai")
}
看到上述代碼,一時間知道怎么走,但是我們看 goland 就知道 panic 后面的語句肯定不會執(zhí)行

嘗試分析一下,前面有說,defer 是按照棧的順序來的
第 1 個 derfer 先入棧
第 2 個 defer 后入棧
執(zhí)行 panic 程序崩潰 應(yīng)該會報錯
i panic
但是程序退出的時候,會出棧,會先執(zhí)行 第 2 個 defer , 這個 defer 也是一個 panic, 則會覆蓋剛才的 panic 信息,應(yīng)該會報錯
defer func ?panic
執(zhí)行出棧,執(zhí)行到第 1 個 defer ,異常被捕獲了,程序正常退出,因此執(zhí)行程序會有如下結(jié)果
xdm,?我捕獲到異常了
好了,今天就到這里,感興趣的朋友也可以玩起來
歡迎點(diǎn)贊,關(guān)注,收藏
朋友們,你的支持和鼓勵,是我堅持分享,提高質(zhì)量的動力

好了,本次就到這里
技術(shù)是開放的,我們的心態(tài),更應(yīng)是開放的。擁抱變化,向陽而生,努力向前行。
我是阿兵云原生,歡迎點(diǎn)贊關(guān)注收藏,下次見~