Go > Error Handling > Panic and Recover > Recovering from panic

Recovering from Panic in Go

This snippet demonstrates how to use the `recover` function in Go to gracefully handle panics and prevent program termination.

Introduction to Panic and Recover

Go's panic mechanism is similar to exceptions in other languages. A panic occurs when the program encounters an unrecoverable error at runtime. When a panic happens, the program normally halts. However, Go provides a built-in function called `recover` that allows you to regain control of a panicking goroutine and prevent the program from crashing. `recover` only works when called directly within a deferred function.

Code Example: Recovering from a Panic

This code demonstrates a function `mightPanic` that could potentially cause a panic (in this case, a division by zero). The `recoverFromPanic` function is defined to handle any panics that occur within `mightPanic`. Importantly, `recoverFromPanic` is called using `defer`, ensuring it's executed even if a panic occurs. If a panic happens, `recover()` will return the value passed to `panic()`, otherwise it returns `nil`. The program will then print a message indicating it recovered and continues execution.

package main

import (
	"fmt"
)

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

func mightPanic(input int) {
	defer recoverFromPanic()

	fmt.Println("Starting mightPanic with input:", input)
	if input == 0 {
		panic("Division by zero!")
	}
	result := 100 / input
	fmt.Println("Result:", result)
}

func main() {
	mightPanic(10)
	mightPanic(0)
	mightPanic(5)
	fmt.Println("Program continues after panics are handled.")
}

Explanation of the Code

1. **`recoverFromPanic` Function:** This function uses `recover()` to check if a panic occurred. If `recover()` returns a non-nil value, it means a panic happened, and we can handle it here. In this case, we print a message to the console. 2. **`mightPanic` Function:** This function simulates a situation that could lead to a panic. The `defer recoverFromPanic()` line ensures that `recoverFromPanic` is always executed before the function returns, regardless of whether a panic occurs. 3. **`panic` Function:** If `input` is 0, the code calls `panic("Division by zero!")`. This triggers a panic, which is then caught by the deferred `recoverFromPanic` function. 4. **`main` Function:** The `main` function calls `mightPanic` with different inputs to demonstrate how the `recover` mechanism works. Note that the program continues to execute even after a panic is recovered from.

Concepts Behind the Snippet

The core concepts here are `defer`, `panic`, and `recover`. `defer` schedules a function call to be run after the surrounding function returns. `panic` initiates a runtime error, stopping normal execution. `recover` allows a program to regain control after a panic.

Real-Life Use Case Section

Recovering from panics is particularly useful in server applications. Imagine a web server handling multiple requests concurrently. If one request causes a panic, you don't want the entire server to crash. By using `recover`, you can catch the panic, log the error, and return an error response to the client, while allowing the server to continue processing other requests. Database connection management and file processing are also excellent use-cases.

Best Practices

  • Use `recover` sparingly: Panics should generally be reserved for truly exceptional situations, not for routine error handling.
  • Log the panic: When recovering from a panic, always log the error message and stack trace for debugging purposes.
  • Clean up resources: Ensure that any resources (files, network connections, etc.) are properly closed or released within the deferred function before recovering.
  • Don't ignore the error: Recovering from a panic doesn't mean the problem is solved. You still need to handle the error appropriately, such as returning an error to the user or retrying the operation.

Interview Tip

Be prepared to explain the difference between `error` and `panic` in Go. Also, be able to describe how `defer` and `recover` work together to handle panics. Expect questions about when to use `panic` versus returning an `error`.

When to Use `recover`

Use `recover` when you want to prevent a panic from crashing your entire program. This is especially important in long-running processes like servers or background workers.

Alternatives

Instead of using `panic` and `recover` for general error handling, prefer returning explicit `error` values. This makes the error handling more explicit and easier to reason about.

Pros and Cons of Using `recover`

  • Pros: Prevents program crashes, allows for graceful error handling in critical sections.
  • Cons: Can mask underlying problems, makes debugging more difficult if not used carefully, can make control flow less obvious.

FAQ

  • What happens if I don't use `recover` when a panic occurs?

    If a panic occurs and there is no `recover` function in the call stack, the program will terminate and print a stack trace to the console.
  • Can I use `recover` outside of a deferred function?

    No, `recover` only works when called directly within a deferred function. Calling it outside of a deferred function will always return `nil`.
  • Is it good practice to use panic/recover instead of error return for expected errors?

    Generally, no. Error returns are preferred for anticipated errors, while panic/recover should be reserved for truly exceptional, unrecoverable situations.