首頁  >  文章  >  後端開發  >  為什麼 `recover()` 無法處理 Go 例程中的恐慌?

為什麼 `recover()` 無法處理 Go 例程中的恐慌?

Susan Sarandon
Susan Sarandon原創
2024-11-06 20:01:03799瀏覽

Why Does `recover()` Fail to Handle Panics in Go Routines?

處理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中文網其他相關文章!

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