深入理解golang的異常處理機(jī)制
前言
眾所周知在java或php等很多面向?qū)ο蟮恼Z(yǔ)言中, 異常處理是依靠throw、catch來(lái)進(jìn)行的。在go語(yǔ)言中,panic和recover函數(shù)在作用層面分別對(duì)等throw和catch語(yǔ)句,當(dāng)然也存在不同之處。下面話(huà)不多說(shuō),來(lái)一起看看詳細(xì)的介紹吧。
從設(shè)計(jì)層面來(lái)看,panic和recover函數(shù)適用于那些真正的異常(例如整數(shù)除0),而throw catch finally機(jī)制常常被用來(lái)處理一些業(yè)務(wù)層面的自定義異常。因此在go語(yǔ)言中,panic和recover要慎用。
上述兩種異常機(jī)制的使用中,在處理異常時(shí)控制流程的走向也是相似的。
下面將分別舉例說(shuō)明:
try catch finally機(jī)制
try{ throw new Exception(); } catch(Exception $e) { do something ... } finally { }
這種機(jī)制中,我們把可能拋出異常的語(yǔ)句或拋出自定義異常的語(yǔ)句放置到try語(yǔ)句塊中,而在catch塊中,我們將上述語(yǔ)句拋出的異常捕獲,針對(duì)不同的異常進(jìn)行報(bào)警或log等處理。之后,控制流程進(jìn)入到finally語(yǔ)句塊中。若沒(méi)有finally語(yǔ)句,控制流程將進(jìn)入到catch之后的語(yǔ)句中。也就是說(shuō),在這種機(jī)制中,控制流程是轉(zhuǎn)移到同一層級(jí)中異常捕獲之后的語(yǔ)句中。
panic recover defer機(jī)制
在go的異常機(jī)制中,panic可以將原有的控制流程中斷,進(jìn)入到一個(gè)"恐慌"流程。這種恐慌流程可以顯式調(diào)用panic()函數(shù)產(chǎn)生或者由運(yùn)行時(shí)錯(cuò)誤產(chǎn)生(例如訪(fǎng)問(wèn)越界的數(shù)組下標(biāo))。panic會(huì)在調(diào)用它的函數(shù)中向本層和它的所有上層逐級(jí)拋出,若一直沒(méi)有recover將其捕獲,程序退出后會(huì)產(chǎn)生crash;若在某層defer語(yǔ)句中被recover捕獲,控制流程將進(jìn)入到recover之后的語(yǔ)句中。
/* example 1 */ package main import ( "fmt" ) func f() { defer func() { fmt.Println("b") if err := recover();err != nil { fmt.Println(err) } fmt.Println("d") }() fmt.Println("a") panic("a bug occur") fmt.Println("c") } func main() { f() fmt.Println("x") }
在上述舉例中,輸出結(jié)果為:
a b a bug occur d x
這說(shuō)明,在f函數(shù)中拋出的panic被自己defer語(yǔ)句中的recover捕獲,然后控制流程進(jìn)入到recover之后的語(yǔ)句中,即打印d、打印x,之后進(jìn)程正常退出。
/* example 2 */ package main import ( "fmt" ) func g() { defer func() { fmt.Println("b") if err := recover();err != nil { fmt.Println(err) } fmt.Println("d") }() f() fmt.Println("e") } func f() { fmt.Println("a") panic("a bug occur") fmt.Println("c") } func main() { g() fmt.Println("x") }
上述案例的輸出結(jié)果是:
a b a bug occur d x
進(jìn)程經(jīng)歷了這樣一個(gè)過(guò)程:f()
中拋出panic,由于自身沒(méi)有定義defer語(yǔ)句,panic被拋到g()中。g()
的defer語(yǔ)句中定義了recover,捕獲panic后并執(zhí)行完defer剩余的語(yǔ)句,之后控制流程被轉(zhuǎn)交到main()
函數(shù)中,直至進(jìn)程結(jié)束。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
詳解Go語(yǔ)言中rand(隨機(jī)數(shù))包的使用
在Golang中,有兩個(gè)包提供了rand,分別為math/rand和crypto/rand對(duì)應(yīng)兩種應(yīng)用場(chǎng)景。math/rand包實(shí)現(xiàn)了偽隨機(jī)數(shù)生成器。也就是生成 整形和浮點(diǎn)型;crypto/rand包實(shí)現(xiàn)了用于加解密的更安全的隨機(jī)數(shù)生成器。本文就來(lái)和大家詳細(xì)講講math/rand的使用2022-08-08Go語(yǔ)言開(kāi)發(fā)編程規(guī)范命令風(fēng)格代碼格式
這篇文章主要為大家介紹了Go語(yǔ)言開(kāi)發(fā)編程規(guī)范命令風(fēng)格代碼格式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06簡(jiǎn)單談?wù)凣olang中的字符串與字節(jié)數(shù)組
這篇文章主要給大家介紹了關(guān)于Golang中字符串與字節(jié)數(shù)組的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法
這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法,涉及Go語(yǔ)言http操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02