日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Goroutine配上Panic會(huì)怎樣?

最近用 Golang 進(jìn)行編碼也有3個(gè)月了,說(shuō)來(lái)慚愧,到現(xiàn)在還沒(méi)正兒八經(jīng)深入學(xué)習(xí)一下 Golang,一直被工作趕著往前在跑。

為白城等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及白城網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、白城網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

最近正好在工作中遇到一個(gè)問(wèn)題,需要對(duì) Golang 中的 goroutine 和 panic & recover 稍做深入的了解,算是忙里偷閑學(xué)習(xí)一下。

對(duì) goroutine 的底層細(xì)節(jié)就不展開(kāi)了,網(wǎng)上有不少相關(guān)的文章解讀,如果你愿意的話,也可以去扒一下 Golang 的源碼。

簡(jiǎn)單對(duì) goroutine 進(jìn)行一下概括就是:

goroutine 實(shí)現(xiàn)了 M:N 的線程模型,是協(xié)程的一種實(shí)現(xiàn)。golang 內(nèi)置的調(diào)度器,可以讓多核 CPU 中每個(gè) CPU 執(zhí)行一個(gè)協(xié)程。

單從表現(xiàn)來(lái)看,你可以將 goroutine 看作是 java 之類編程語(yǔ)言中的多線程的運(yùn)行效果。

好了,那么問(wèn)題來(lái)了:goroutine 中發(fā)生 panic 會(huì)怎樣?

話不多說(shuō),實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),我們直接上手 coding。

func main()  {
go panicInGoroutine()

//以下3行代碼是為了讓控制臺(tái)掛起,等待gorouine運(yùn)行完畢。
fmt.Println("wait")
input := bufio.NewScanner(os.Stdin)
input.Scan()
}

func panicInGoroutine() {
panic("panic in goroutine.")
}

運(yùn)行代碼的結(jié)果如下:

可以看到,整個(gè)程序都崩了。

那么,如果在 goroutine 里的 goroutine 發(fā)出 panic 呢?也是一樣的效果,程序崩了。

可能你會(huì)覺(jué)得整個(gè)程序之所以會(huì)崩,是因?yàn)楫惓1粚訉由蠏伒街骶€程導(dǎo)致的,其實(shí)并非如此。在 Golang 中,任何地方發(fā)生的任意一個(gè) panic,都會(huì)直接程序退出。

那么怎么才能讓程序不退出呢?

通過(guò)調(diào)用 recover() 方法來(lái)捕獲 panic 并恢復(fù)將要崩掉的程序。

func main() {
go panicInGoroutine()

//以下3行代碼是為了讓控制臺(tái)掛起,等待gorouine運(yùn)行完畢。
fmt.Println("wait")
input := bufio.NewScanner(os.Stdin)
input.Scan()
}

func panicInGoroutine() {
//recover()必須要和defer配合一起用,確保一旦執(zhí)行到該方法體,這里定義的defer方法一定會(huì)被執(zhí)行,哪怕是發(fā)生了panic。
defer func() {
err := recover()
if err != nil {
fmt.Printf("recover receive a err: %+v \n", err)
}
}()

panic("panic in goroutine.")
}

執(zhí)行上面的代碼,結(jié)果如下:

可以看到,程序沒(méi)有再崩了。那么新的問(wèn)題又來(lái)了,能不能把 recover() 放到最外層的方法里,這樣可以更好地實(shí)現(xiàn)一次 recover() 覆蓋當(dāng)前方法其下所有的 panic。

func main() {
defer func() {
err := recover()
if err != nil {
fmt.Printf("recover receive a err: %+v \n", err)
}
}()

go panicInGoroutine()

//以下3行代碼是為了讓控制臺(tái)掛起,等待gorouine運(yùn)行完畢。
fmt.Println("wait")
input := bufio.NewScanner(os.Stdin)
input.Scan()
}

func panicInGoroutine() {
panic("panic in goroutine.")
}

運(yùn)行之后的結(jié)果:

竟然還是崩了。如果你是一位 Java 或者 .Net 的程序員習(xí)慣了 try-catch-finally 的運(yùn)行效果肯定對(duì)這個(gè)結(jié)果比較意外。在父方法定義的 recover() 竟然無(wú)法捕獲到子方法里的 panic。

其實(shí)這里的原因是,外層方法中定義的 recover() 無(wú)法捕獲通過(guò) goroutine 執(zhí)行的子方法中拋出的 panic。在上面的代碼中,我們把 go panicInGoroutine() 前面的 go 去掉就可以正常捕獲了。

好了,那么根據(jù)以上這些信息得到的處理 panic 的正確姿勢(shì)是什么呢?

  • 必須通過(guò) defer 關(guān)鍵字來(lái)調(diào)用 recover()。
  • 當(dāng)通過(guò) goroutine 調(diào)用某個(gè)方法,一定要確保內(nèi)部有 recover() 機(jī)制。

如果你想進(jìn)一步深入了解 panic 和 recove r的機(jī)制,分享你一個(gè)超棒的硬核視頻:https://www.bilibili.com/video/BV155411Y7XT,第一遍看可能會(huì)有點(diǎn)暈,建議反復(fù)看,直到完全理解其原理。


文章題目:Goroutine配上Panic會(huì)怎樣?
網(wǎng)頁(yè)網(wǎng)址:http://m.5511xx.com/article/dpihpce.html