欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang中panic的異常處理

 更新時(shí)間:2022年08月17日 10:08:05   作者:CarlosKeFeng  
本文主要介紹了Golang中panic的異常處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

Golang中當(dāng)程序發(fā)生致命異常時(shí)(比如數(shù)組下標(biāo)越界,注意這里的異常并不是error),Golang程序會(huì)panic(運(yùn)行時(shí)恐慌)。當(dāng)程序發(fā)生panic時(shí),程序會(huì)執(zhí)行當(dāng)前棧中的defer 函數(shù)列表。然后打印引發(fā)panic的具體信息,最后進(jìn)程退出,本篇文章我們一起探討Golang中的panic以及如何利用defer 和 recover 來(lái)恢復(fù)這種致命的異常

分析造成panic堆棧信息

func main() {
?? ?f1()
?? ?fmt.Println("main func end")
}

func f1() {
?? ?fmt.Println("func f1 start")
?? ?arr := []int{}
?? ?fmt.Println(arr[10])
?? ?fmt.Println("func f1 end")
}

上述代碼中,我在main函數(shù)(主協(xié)程)中調(diào)用了f1函數(shù),在調(diào)用完該函數(shù)后,我打印了「main func end」,程序如果正常執(zhí)行的話(huà)會(huì)輸出

func f1 start
func f1 end
main func end

很明顯我們可以看出 f1 函數(shù)中,切片arr是沒(méi)有索引為10的元素的,這個(gè)時(shí)候程序運(yùn)行時(shí)會(huì)造成panic,下面是程序panic時(shí),console打印的堆棧信息

func f1 start
panic: runtime error: index out of range [10] with length 0
goroutine 1 [running]:
main.f1()
/Users/carlos/go/src/test/demo01.go:15 +0x78
main.main()
/Users/carlos/go/src/test/demo01.go:8 +0x20
Process finished with the exit code 2

我們從堆棧中可以發(fā)現(xiàn):

程序會(huì)在造成panic所處的位置終止

我們可以看到錯(cuò)誤信息中只輸出了 func f1 start

產(chǎn)生panic的原因

panic: runtime error: index out of range [10] with length 0

是哪里造成的panic

goroutine 1 [running] // 運(yùn)行該程序的協(xié)程
main.f1()
/Users/carlos/go/src/test/demo01.go:15 +0x78 // f1 函數(shù),當(dāng)前demo01文件的低15行
main.main()
/Users/carlos/go/src/test/demo01.go:8 +0x20 // main 函數(shù),當(dāng)前文件的弟8行

從上面的panic詳情我們可以看出,錯(cuò)誤鏈?zhǔn)峭ㄟ^(guò)棧的形式展現(xiàn)出來(lái)的(mian函數(shù)先調(diào)用,然后在mian中調(diào)用f1),所以大家以后在程序發(fā)生panic時(shí)查看堆棧信息時(shí)可以先看最上層的錯(cuò)誤,因?yàn)檫@里是造成panic的根本原因

如何恢復(fù)panic造成的程序崩潰

Golang中提供了recover函數(shù)用來(lái)恢復(fù)因panic造成的程序崩潰。recover函數(shù)有一個(gè)返回值來(lái)告訴我們panic產(chǎn)生的具體原因。下面我們通過(guò)代碼來(lái)進(jìn)行演示

func main() {
?? ?f1()
?? ?r := recover()
?? ?fmt.Printf("%s \n", r)
?? ?fmt.Println("main func end")
}

func f1() {
?? ?fmt.Println("func f1 start")
?? ?arr := []int{}
?? ?fmt.Println(arr[10])
?? ?fmt.Println("func f1 end")
}

上述代碼中我只是在調(diào)用f1函數(shù)的下一行調(diào)用了recover函數(shù),這樣一來(lái)我們的理想狀態(tài)了能夠恢復(fù)程序,讓程序執(zhí)行完main函數(shù)中剩下的代碼(打印panic信息,最后打印 main func end),當(dāng)我們運(yùn)行該程序的時(shí)候發(fā)現(xiàn)recover并沒(méi)有起到作用,這是因?yàn)楫?dāng)f1造成panic時(shí),f1下方的recover函數(shù)根本沒(méi)有機(jī)會(huì)執(zhí)行。

下面我將上述代碼進(jìn)行一個(gè)簡(jiǎn)單的改造:

func main() {
?? ?defer func() {
?? ??? ?fmt.Println("defer func start")
?? ??? ?if r := recover(); r != nil {
?? ??? ??? ?fmt.Printf("%s \n", r)
?? ??? ?}
?? ??? ?fmt.Println("defer func end")
?? ?}()
?? ?f1()
?? ?fmt.Println("main func end")
}

func f1() {
?? ?fmt.Println("func f1 start")
?? ?arr := []int{}
?? ?fmt.Println(arr[10])
?? ?fmt.Println("func f1 end")
}

輸出

func f1 start
defer func start
runtime error: index out of range [10] with length 0 
defer func end

上述代碼中,我只是在main函數(shù)最開(kāi)頭添加了一個(gè)defer 函數(shù),并在該函數(shù)中調(diào)用了recover函數(shù)。注意,我們?cè)谖恼碌淖铋_(kāi)頭已經(jīng)說(shuō)明了,當(dāng)程序發(fā)生panic時(shí),程序會(huì)依次執(zhí)行棧中的defer函數(shù)(關(guān)于defer函數(shù)請(qǐng)閱讀官網(wǎng)描述)。所以當(dāng)前程序發(fā)生panic時(shí)在進(jìn)程退出之前會(huì)走到defer函數(shù)中執(zhí)行recover函數(shù),recover函數(shù)會(huì)恢復(fù)當(dāng)前進(jìn)程并打印錯(cuò)誤信息。

這里我需要特別提醒你一點(diǎn),最好將defer語(yǔ)句寫(xiě)在函數(shù)的最前面。如果上述例子我將f1的調(diào)用寫(xiě)在defer函數(shù)之前,你會(huì)發(fā)現(xiàn)recover函數(shù)還是沒(méi)有執(zhí)行

func main() {
?? ?f1()
?? ?defer func() {
?? ??? ?fmt.Println("defer func start")
?? ??? ?if r := recover(); r != nil {
?? ??? ??? ?fmt.Printf("%s \n", r)
?? ??? ?}
?? ??? ?fmt.Println("defer func end")
?? ?}()
?? ?fmt.Println("main func end")
}

這是因?yàn)閒1造成panic時(shí),defer函數(shù)根本就沒(méi)有壓入函數(shù)調(diào)用棧中。

何時(shí)使用panic

當(dāng)你的項(xiàng)目中特別依賴(lài)一些組件時(shí),比如一些web項(xiàng)目中經(jīng)常會(huì)在進(jìn)程啟動(dòng)之前初始化一些mysql,mq句柄。這些實(shí)例對(duì)業(yè)務(wù)來(lái)說(shuō)是非常重要的,所以當(dāng)這些實(shí)例初始化失敗時(shí)我們可以直接讓當(dāng)前程序panic(手動(dòng)panic),然后及時(shí)發(fā)現(xiàn)問(wèn)題并解決。這樣總比你帶著問(wèn)題上線(xiàn)后,然后一批流入打入進(jìn)來(lái),客戶(hù)端瘋狂報(bào)錯(cuò)要好

Golang中手動(dòng)調(diào)用panic:

func main() {
?? ?initMysql()
}

func initMysql() {
?? ?panic("init mysql failed") // panic可以接收一個(gè)interface類(lèi)型的參數(shù)
}

到此這篇關(guān)于Golang中panic的異常處理的文章就介紹到這了,更多相關(guān)Golang panic內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言實(shí)現(xiàn)棧與隊(duì)列基本操作學(xué)家

    Go語(yǔ)言實(shí)現(xiàn)棧與隊(duì)列基本操作學(xué)家

    go語(yǔ)言中,并沒(méi)有棧與隊(duì)列相關(guān)的數(shù)據(jù)結(jié)構(gòu),但是我們可以借助切片來(lái)實(shí)現(xiàn)棧與隊(duì)列的操作;接下來(lái)我們一起實(shí)現(xiàn)棧與隊(duì)列基本操作,感興趣的可以了解一下
    2022-11-11
  • golang中package?is?not?in?GOROOT報(bào)錯(cuò)的真正解決辦法

    golang中package?is?not?in?GOROOT報(bào)錯(cuò)的真正解決辦法

    這篇文章主要給大家介紹了關(guān)于golang中package?is?not?in?GOROOT報(bào)錯(cuò)的真正解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)同樣遇到這個(gè)問(wèn)題的朋友具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-03-03
  • GoLang使goroutine停止的五種方法實(shí)例

    GoLang使goroutine停止的五種方法實(shí)例

    goroutine是Go并行設(shè)計(jì)的核心,下面這篇文章主要給大家介紹了關(guān)于GoLang使goroutine停止的五種方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Golang編程實(shí)現(xiàn)生成n個(gè)從a到b不重復(fù)隨機(jī)數(shù)的方法

    Golang編程實(shí)現(xiàn)生成n個(gè)從a到b不重復(fù)隨機(jī)數(shù)的方法

    這篇文章主要介紹了Golang編程實(shí)現(xiàn)生成n個(gè)從a到b不重復(fù)隨機(jī)數(shù)的方法,結(jié)合實(shí)例形式分析了Go語(yǔ)言字符串操作及隨機(jī)數(shù)生成的相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • Golang實(shí)現(xiàn)AES加密和解密的示例代碼

    Golang實(shí)現(xiàn)AES加密和解密的示例代碼

    AES( advanced encryption standard)使用相同密鑰進(jìn)行加密和解密,也就是對(duì)稱(chēng)加密。本文將詳細(xì)講解Golang實(shí)現(xiàn)AES加密和解密的方法,感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • Golang中可比較的數(shù)據(jù)類(lèi)型詳解

    Golang中可比較的數(shù)據(jù)類(lèi)型詳解

    在日常開(kāi)發(fā)中,比較操作是最常用的基本操作之一,可以用來(lái)判斷變量之間是否相等或者對(duì)應(yīng)的大小關(guān)系,本文將深入解析 Golang 中可比較的數(shù)據(jù)類(lèi)型,并結(jié)合代碼示例來(lái)說(shuō)明如何在不同情況下進(jìn)行比較,需要的朋友可以參考下
    2024-01-01
  • 使用Viper處理Go應(yīng)用程序的配置方法

    使用Viper處理Go應(yīng)用程序的配置方法

    Viper是一個(gè)應(yīng)用程序配置解決方案,用于Go應(yīng)用程序,它支持JSON、TOML、YAML、HCL、envfile和Java properties配置文件格式,這篇文章主要介紹了使用Viper處理Go應(yīng)用程序的配置,需要的朋友可以參考下
    2023-09-09
  • Golang中的錯(cuò)誤處理的示例詳解

    Golang中的錯(cuò)誤處理的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Golang中的錯(cuò)誤處理的相關(guān)資料,文章中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Golang有一定幫助,需要的可以參考一下
    2022-12-12
  • GO語(yǔ)言Context的作用及各種使用方法

    GO語(yǔ)言Context的作用及各種使用方法

    golang的Context包是專(zhuān)門(mén)用來(lái)處理多個(gè)goroutine之間與請(qǐng)求域的數(shù)據(jù)、取消信號(hào)、截止時(shí)間等相關(guān)操作,下面這篇文章主要給大家介紹了關(guān)于GO語(yǔ)言Context的作用及各種使用方法的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • 詳解Go語(yǔ)言中new和make關(guān)鍵字的區(qū)別

    詳解Go語(yǔ)言中new和make關(guān)鍵字的區(qū)別

    本篇文章來(lái)介紹一道非常常見(jiàn)的面試題,到底有多常見(jiàn)呢?可能很多面試的開(kāi)場(chǎng)白就是由此開(kāi)始的。那就是 new 和 make 這兩個(gè)內(nèi)置函數(shù)的區(qū)別,希望對(duì)大家有所幫助
    2023-03-03

最新評(píng)論