目錄
- 一 panic機(jī)制
- 二 實(shí)例
- 2.1 main用recover
- 2.2 func用recover
- 2.3 func用recover且開創(chuàng)goroutine
- 2.4 goroutine中panic
- 2.5 func1內(nèi)嵌func2中panic且func2做處理
- 2.6 func1內(nèi)嵌func中panic且func1做處理
一 panic機(jī)制
panic會(huì)將這個(gè)異常不斷向上拋出,直到有地方處理它,如果有處理,則不會(huì)再向上拋出。倘若沒有處理,那么最終會(huì)導(dǎo)致main掛掉.
golang雖然沒有try catch機(jī)制,卻有一種類似的recover機(jī)制,后續(xù)demo我們可以觀測到它的用法和作用
二 實(shí)例
2.1 main用recover
func main() {
defer func() {
if err := recover(); err != nil {
log.Println("err:", err)
}
}()
go test1()
time.Sleep(time.Second * 3)
panic(errors.New("stop test1"))
log.Println("123")
select {}
}
func test1() {
for {
tm := time.NewTicker(time.Second)
select {
case -tm.C:
log.Println("test1")
}
}
}

2.2 func用recover
func main() {
defer func() {
if err := recover(); err != nil {
log.Println("err:", err)
}
}()
go test1()
time.Sleep(time.Second * 3)
makeerr()
log.Println("123")
select {}
}
func test1() {
for {
tm := time.NewTicker(time.Second)
select {
case -tm.C:
log.Println("test1")
}
}
}
func makeerr() {
defer func() {
if err := recover(); err != nil {
log.Println("makeerr:", err)
}
}()
panic(errors.New("stop"))
}

此時(shí)我們?cè)趂unc中用recover,那么掛掉的只是func,他不會(huì)拋到main中,所以main能繼續(xù)運(yùn)行,繼而main開辟的go test1也能繼續(xù)運(yùn)行
2.3 func用recover且開創(chuàng)goroutine
func main() {
defer func() {
if err := recover(); err != nil {
log.Println("err:", err)
}
}()
time.Sleep(time.Second * 3)
makeerr()
log.Println("123")
select {}
}
func test1() {
for {
tm := time.NewTicker(time.Second)
select {
case -tm.C:
log.Println("test1")
}
}
}
func makeerr() {
defer func() {
if err := recover(); err != nil {
log.Println("makeerr err:", err)
}
}()
go test1()
panic(errors.New("stop test"))
}

我們發(fā)現(xiàn),func雖然掛掉了,但是他開創(chuàng)的go沒掛掉,因?yàn)榧词故沁@個(gè)函數(shù)退出了,新開的協(xié)程是相當(dāng)于基于main下的一個(gè)子程,只要main不退出,他依然會(huì)“存活”
2.4 goroutine中panic
func main() {
defer func() {
if err := recover(); err != nil {
log.Println("err:", err)
}
}()
go test1()
time.Sleep(time.Second * 3)
log.Println("123")
select {}
}
func test1() {
log.Println("test1 start")
panic(errors.New("stop test1"))
log.Println("test1 end")
}

協(xié)程中如果沒recover,那么error就會(huì)拋向main,main就會(huì)掛掉,從而沒有執(zhí)行到后面的log打印。
---> 這種情況,main中做defer recover是沒用的
2.5 func1內(nèi)嵌func2中panic且func2做處理
func main() {
test1()
time.Sleep(time.Second * 3)
log.Println("123")
}
func test1() {
log.Println("test1 start")
test2()
log.Println("test1 end")
}
func test2() {
defer func() {
if err := recover(); err != nil {
log.Println("test2 err:", err)
}
}()
log.Println("test2 start")
panic(errors.New("stop test2"))
log.Println("test2 end")
}

2.6 func1內(nèi)嵌func中panic且func1做處理
func main() {
test1()
time.Sleep(time.Second * 3)
log.Println("123")
}
func test1() {
defer func() {
if err := recover(); err != nil {
log.Println("test? err:", err)
}
}()
log.Println("test1 start")
test2()
log.Println("test1 end")
}
func test2() {
log.Println("test2 start")
panic(errors.New("stop test2"))
log.Println("test2 end")
}

func2異常,執(zhí)行終止,向調(diào)用者func1拋出進(jìn)而本身退出,func1得到異常,執(zhí)行終止,本身退出時(shí)recover進(jìn)行處理,從而?;盍薽ain
到此這篇關(guān)于golang panic及處理機(jī)制的文章就介紹到這了,更多相關(guān)golang panic內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Golang捕獲panic堆棧信息的講解
- Golang中異常處理機(jī)制詳解
- GoLang 逃逸分析的機(jī)制詳解
- 深入理解golang的異常處理機(jī)制