Home  >  Article  >  Backend Development  >  Why Does `recover()` Fail to Handle Panics in Go Routines?

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

Susan Sarandon
Susan SarandonOriginal
2024-11-06 20:01:03799browse

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

Handling Panics in Go Routines

Go routines provide concurrency in Go programs, but panics within these routines can pose challenges. To recover from panics, the recover() function is typically employed. However, there are instances where recover() fails to operate as expected within goroutines.

Understanding the Failure of Recovery in Go Routines

Consider the following code block:

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
}

This code attempts to recover from a panic in a goroutine using a deferred function in the main function. However, it fails to recover the panic. Conversely, the following code block operates as expected:

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
}

Resolving the Recovery Issue

The key to understanding this behavior lies in the nature of goroutines. recover() can only recover from panics that occur within the same goroutine where it is called. From the Go blog:

The process continues up the stack until all functions in the current goroutine have returned, at which point the program crashes

To handle panics in goroutines, one needs to use a deferred recovery function within the goroutine itself.

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
}

By placing the recovery function within the goroutine, one can intercept panics and handle them appropriately.

The above is the detailed content of Why Does `recover()` Fail to Handle Panics in Go Routines?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn