Go > Core Go Basics > Functions > Panic and recover
Panic and Recover in Go
This code demonstrates how to use panic and recover in Go to handle unexpected errors and prevent program crashes. It shows a simple scenario where a function panics due to an invalid index access, and how recover can be used to gracefully handle the panic and continue execution.
Basic Panic Example
This code showcases a basic example where the 'mightPanic' function might cause a panic if the supplied index is out of bounds for the array. When the 'panic' function is called, normal execution stops, and the program prints the panic message to standard error and terminates. Try running this to observe the panic.
package main
import (
"fmt"
)
func mightPanic(index int) {
arr := []int{1, 2, 3}
fmt.Println("Accessing index:", index)
if index >= len(arr) {
panic("Index out of bounds!")
}
fmt.Println("Value at index:", arr[index])
}
func main() {
mightPanic(0)
mightPanic(5)
mightPanic(1)
fmt.Println("Program continues...")
}
Recovering from a Panic
This example demonstrates the use of 'recover'. The 'safeFunction' uses a 'defer' statement with an anonymous function that calls 'recover'. If 'mightPanic' panics, 'recover' will catch the panic, allowing the program to continue execution instead of crashing. Note that recover only works within the deferred function.
package main
import (
"fmt"
)
func mightPanic(index int) {
arr := []int{1, 2, 3}
fmt.Println("Accessing index:", index)
if index >= len(arr) {
panic("Index out of bounds!")
}
fmt.Println("Value at index:", arr[index])
}
func safeFunction(index int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
mightPanic(index)
fmt.Println("Continuing after mightPanic...")
}
func main() {
safeFunction(0)
safeFunction(5)
safeFunction(1)
fmt.Println("Program continues...")
}
Concepts Behind Panic and Recover
panic
is a built-in function that stops the normal execution flow of a goroutine. When panic
is called, deferred functions are executed in reverse order. recover
is a built-in function that regains control of a panicking goroutine. It's only useful inside deferred functions. recover
stops the panicking sequence by restoring normal execution and retrieves the error value passed to panic
. If you call recover
outside of a deferred function, it will not stop a panicking sequence. The return value of recover
will be nil
if the current goroutine is not panicking.
Real-Life Use Case
Panic
and recover
are useful when dealing with unexpected errors that should not normally happen in the application. Examples include accessing a configuration value that is expected to be present but is missing due to deployment issues, or handling unexpected input in a data processing pipeline. They can also be used to handle errors from libraries that might panic when encountering severe issues, allowing your application to gracefully recover and log the error rather than crashing. For example, handling malformed regular expressions or corrupted data files.
Best Practices
Prefer error handling with explicit return values over panic
and recover
for anticipated errors. Use panic
sparingly, primarily for unrecoverable errors that indicate a serious problem. Always use recover
within a deferred function. Log the recovered error for debugging and auditing purposes. Avoid using panic
for normal control flow. Document when and why your code might panic, so other developers are aware of the potential for panics and can handle them appropriately.
Interview Tip
Be prepared to explain the difference between error handling with return values and using panic
and recover
. Know when it's appropriate to use each approach. Understand that recover
must be called within a deferred function to be effective. Be prepared to demonstrate an example of how to use panic
and recover
to handle unexpected errors.
When to Use Them
Use panic
when a program reaches a state where it cannot continue execution safely. Use recover
to gracefully handle panics and prevent program crashes, especially in long-running services. For example, you may want to use recover in a web server to ensure that a panic in one request does not bring down the entire server.
Alternatives
The primary alternative to using panic
and recover
is to use explicit error handling with return values. This allows you to handle errors gracefully at the point where they occur, rather than relying on unwinding the call stack. Another alternative is to use error wrapping libraries that provide more context and information about errors. Some libraries also offer structured error handling techniques.
Pros
Panic
and recover
can provide a centralized way to handle unexpected errors. Recover
prevents program crashes and allows execution to continue. They can simplify error handling in some cases, especially when dealing with errors deep within a call stack.
Cons
Overuse of panic
and recover
can make code harder to understand and debug. It can obscure the control flow of the program. Relying on panic
and recover
can mask underlying issues and prevent proper error handling. They can also impact performance because unwinding the stack is resource intensive.
FAQ
-
What happens if recover is not called within a deferred function?
Ifrecover
is not called within a deferred function, it will not catch any panics, and the program will crash. -
Can I recover from multiple panics?
No,recover
only handles the first panic in a given goroutine. Subsequent panics will not be caught by the samerecover
. -
Should I use panic for normal error handling?
No,panic
should be reserved for exceptional situations where the program cannot continue safely. Use explicit error handling with return values for normal errors.