處理Go 例程中的恐慌
Go 例程在Go 程序中提供並發性,但這些例程中的恐慌可能會帶來挑戰。為了從恐慌中恢復,通常使用recover()函數。然而,在某些情況下,recover() 在 Goroutine 中無法如預期運作。
了解Go 例程中恢復失敗
考慮以下程式碼區塊:
func main() { done := make(chan int64) defer fmt.Println("Graceful End of program") defer func() { r := recover() if _, ok := r.(error); ok { fmt.Println("Recovered") } }() go handle(done) for { select{ case <- done: return } } } func handle(done chan int64) { var a *int64 a = nil fmt.Println(*a) done <- *a }
此程式碼嘗試使用main 中的延遲函數從goroutine中的恐慌中恢復功能。然而,它未能挽回恐慌。相反,以下程式碼區塊如預期運作:
func main() { done := make(chan int64) defer fmt.Println("Graceful End of program") defer func() { r := recover() if _, ok := r.(error); ok { fmt.Println("Recovered") } }() handle(done) for { select{ case <- done: return } } } func handle(done chan int64) { var a *int64 a = nil fmt.Println(*a) done <- *a }
解決復原問題
理解這種行為的關鍵在於 goroutine 的本質。 receive() 只能從調用它的同一 goroutine 中發生的恐慌中恢復。來自Go 部落格:
過程繼續在堆疊中向上進行,直到當前goroutine 中的所有函數都返回,此時程式崩潰
要處理goroutine 中的恐慌,需要使用goroutine 內部的延遲恢復函數。
func handle(done chan int64) { defer func() { if r := recover(); r != nil { if _, ok := r.(error); ok { fmt.Println("Recovered in goroutine") } } }() var a *int64 a = nil fmt.Println(*a) done <- *a }
透過將恢復函數放置在 goroutine 內,可以攔截恐慌並處理適當地使用它們。
以上是為什麼 `recover()` 無法處理 Go 例程中的恐慌?的詳細內容。更多資訊請關注PHP中文網其他相關文章!