Start Coding

Topics

Go Panic and Recover

In Go programming, panic and recover are powerful mechanisms for handling exceptional situations and errors. They provide a way to interrupt normal program execution and recover from unexpected runtime errors.

Understanding Panic

A panic is a built-in function that stops the ordinary flow of control and begins panicking. It's typically used when the program encounters a situation it cannot handle.


func main() {
    panic("Something went terribly wrong!")
}
    

When a function calls panic, execution of that function stops immediately. Any deferred functions are then executed as usual.

Recover: Regaining Control

recover is a built-in function that regains control of a panicking goroutine. It's only useful inside deferred functions.


func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    panic("Panic!")
}
    

In this example, the recover function catches the panic and allows the program to continue execution.

Best Practices

  • Use panic for unrecoverable errors where the program cannot continue.
  • Prefer error handling with Go Error Interface for most scenarios.
  • Always use recover in deferred functions.
  • Be cautious when using panic in libraries, as it affects the calling code.

When to Use Panic and Recover

While Go encourages explicit error handling, panic and recover are useful in certain situations:

  1. Handling truly exceptional conditions (e.g., out of memory).
  2. Simplifying error handling in complex recursive functions.
  3. Recovering from panics in Go Goroutines to prevent program crashes.

Relationship with Defer

defer plays a crucial role in panic and recover mechanisms. It ensures that certain functions are called even if a panic occurs.


func example() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in example:", r)
        }
    }()
    fmt.Println("Calling g.")
    g(0)
    fmt.Println("Returned normally from g.")
}

func g(i int) {
    if i > 3 {
        fmt.Println("Panicking!")
        panic(fmt.Sprintf("%v", i))
    }
    defer fmt.Println("Defer in g", i)
    fmt.Println("Printing in g", i)
    g(i + 1)
}
    

This example demonstrates how defer, panic, and recover work together in a more complex scenario.

Conclusion

While panic and recover are powerful tools in Go, they should be used judiciously. For most error handling scenarios, prefer using the Go Error Interface and explicit error checking. Reserve panic for unrecoverable errors or situations where the program cannot continue safely.