Golang中panic的異常處理_第1頁(yè)
Golang中panic的異常處理_第2頁(yè)
Golang中panic的異常處理_第3頁(yè)
Golang中panic的異常處理_第4頁(yè)
Golang中panic的異常處理_第5頁(yè)
已閱讀5頁(yè),還剩1頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Golang中panic的異常處理目錄前言如何恢復(fù)panic造成的程序崩潰何時(shí)使用panic

前言

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堆棧信息

funcmain(){

f1()

fmt.Println("mainfuncend")

funcf1(){

fmt.Println("funcf1start")

arr:=[]int{}

fmt.Println(arr[10])

fmt.Println("funcf1end")

}

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

funcf1start

funcf1end

mainfuncend

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

funcf1start

panic:runtimeerror:indexoutofrange[10]withlength0

goroutine1[running]:

main.f1()

/Users/carlos/go/src/test/demo01.go:15+0x78

main.main()

/Users/carlos/go/src/test/demo01.go:8+0x20

Processfinishedwiththeexitcode2

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

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

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

產(chǎn)生panic的原因

panic:runtimeerror:indexoutofrange[10]withlength0

是哪里造成的panic

goroutine1[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)行演示

funcmain(){

f1()

r:=recover()

fmt.Printf("%s\n",r)

fmt.Println("mainfuncend")

funcf1(){

fmt.Println("funcf1start")

arr:=[]int{}

fmt.Println(arr[10])

fmt.Println("funcf1end")

}

上述代碼中我只是在調(diào)用f1函數(shù)的下一行調(diào)用了recover函數(shù),這樣一來(lái)我們的理想狀態(tài)了能夠恢復(fù)程序,讓程序執(zhí)行完main函數(shù)中剩下的代碼(打印panic信息,最后打印mainfuncend),當(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)單的改造:

funcmain(){

deferfunc(){

fmt.Println("deferfuncstart")

ifr:=recover();r!=nil{

fmt.Printf("%s\n",r)

}

fmt.Println("deferfuncend")

}()

f1()

fmt.Println("mainfuncend")

funcf1(){

fmt.Println("funcf1start")

arr:=[]int{}

fmt.Println(arr[10])

fmt.Println("funcf1end")

}

輸出

funcf1start

deferfuncstart

runtimeerror:indexoutofrange[10]withlength0

deferfuncend

上述代碼中,我只是在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í)行

funcmain(){

f1()

deferfunc(){

fmt.Println("deferfuncstart")

ifr:=recover();r!=nil{

fmt.Printf("%s\n",r)

}

fmt.Println("deferfuncend")

}()

fmt.Println("mainfuncend")

}

這是因?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)題并解決。這樣總比你

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論