首頁 >後端開發 >Golang >Go 如何處理子 Goroutine 中的恐慌,以及為什麼不能從父親 Goroutines 中恢復它們?

Go 如何處理子 Goroutine 中的恐慌,以及為什麼不能從父親 Goroutines 中恢復它們?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-10-31 05:45:02276瀏覽

How Does Go Handle Panics in Child Goroutines, and Why Can't They Be Recovered from the Parent?

從子協程恐慌中恢復的機制是什麼?

Go 中的恐慌處理是管理執行階段錯誤的關鍵面向。在像 goroutine 這樣的多執行緒環境中,問題出現了:呼叫者函數如何有效地從子 goroutine 中發生的恐慌中恢復?

最初,看起來 goroutine 中的恐慌將不可避免地終止程序,特別是如果呼叫者函數在恐慌發生之前完成執行。然而,一個簡單的例子證明了事實並非如此:

<code class="go">func fun1() {
  defer func() {
    if err := recover(); err != nil {
      fmt.Println("recover in func1")
    }
  }()

  go fun2()

  time.Sleep(10 * time.Second)
  fmt.Println("fun1 ended")
}

func fun2() {
  time.Sleep(5 * time.Second)
  panic("fun2 booom!")
  fmt.Println("fun2 ended")
}</code>

在這個例子中,呼叫者函數 fun1 推遲了從任何潛在的恐慌中恢復的調用。令人驚訝的是,即使 fun1 在 fun2 恐慌之前完成執行,程式也不會終止,並且 fun1 中的延遲恢復機制也不會啟動。為什麼會出現這種情況?

Go 規範給出了答案:

即將發布的Go 規範摘錄

根據規範,當發生Panic 時在函數中,當前函數的執行被終止,並且該函數的延遲函數照常執行。隨後,呼叫者函數的延遲函數(直到 goroutine 中的頂級函數)也被執行。 但是,如果panic發生在goroutine的頂層函數中,程式就會終止,並報告錯誤狀況。

在上面的例子中,fun2是頂層-發生恐慌的 goroutine 中的 level 函數。由於 fun2 中沒有延遲恢復機制,因此無論呼叫函數 fun1 中是否存在延遲恢復機制,程式都會在發生恐慌時終止。

這種行為凸顯了一個基本限制:goroutines 無法恢復來自其他 goroutine 中發生的恐慌。每個goroutine都有自己獨立的執行上下文,一個goroutine中的異常或錯誤不能被另一個goroutine處理。因此,有必要相應地處理每個 goroutine 中潛在的恐慌。

以上是Go 如何處理子 Goroutine 中的恐慌,以及為什麼不能從父親 Goroutines 中恢復它們?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn