Defer, Panic, and Recover
In this lesson, you will learn how Go handles unexpected runtime situations using defer, panic, and recover. These features are essential for building safe, stable, and production-ready Go applications.
Unlike traditional exception-based languages, Go provides controlled mechanisms to manage cleanup and recover from serious failures without crashing the entire program.
What Is defer?
The defer keyword schedules a function call to be executed
after the surrounding function finishes execution.
Deferred functions run even if an error or panic occurs.
Basic defer Example
func main() {
defer fmt.Println("World")
fmt.Println("Hello")
}
Output:
Hello
World
The deferred statement executes after the function completes.
Why defer Is Useful
defer is commonly used for:
- Closing files
- Releasing resources
- Unlocking mutexes
- Logging execution time
Real-World Example: File Handling
file, err := os.Open("data.txt")
if err != nil {
return
}
defer file.Close()
This guarantees the file is closed, even if later code fails.
Deferred Calls Stack (LIFO)
When multiple deferred calls exist, Go executes them in Last-In-First-Out (LIFO) order.
func demo() {
defer fmt.Println("One")
defer fmt.Println("Two")
defer fmt.Println("Three")
}
Output:
Three
Two
One
What Is panic?
panic is used to signal a serious problem that the program
cannot continue from normally.
When a panic occurs:
- Normal execution stops
- Deferred functions still run
- The program crashes if not recovered
Basic panic Example
func divide(a int, b int) int {
if b == 0 {
panic("division by zero")
}
return a / b
}
Panics should be used only for unrecoverable errors.
When NOT to Use panic
- Invalid user input
- Expected runtime errors
- Normal control flow
For these cases, return errors instead of panicking.
What Is recover?
recover allows a program to regain control after a panic.
It can only be used inside a deferred function.
Basic recover Example
func safeDivide(a int, b int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from:", r)
}
}()
fmt.Println(a / b)
}
If division by zero occurs, the program recovers instead of crashing.
Real-World Example: API Safety
Recovering from unexpected panics in web servers prevents total crashes.
func handler() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Internal error:", err)
}
}()
panic("database connection failed")
}
Defer + Panic + Recover Flow
Execution order:
- Function executes
- Panic occurs
- Deferred functions execute
- Recover handles the panic (if present)
Common Mistakes
- Using panic for normal errors
- Calling recover outside defer
- Swallowing panics silently
- Overusing recover in business logic
Best Practices
- Use
deferfor cleanup - Use
paniconly for unrecoverable states - Use
recoverat application boundaries - Prefer errors for normal failure handling
What’s Next?
In the next lesson, you will learn about File Handling in Go and how to safely read and write files using Go’s standard library.