Go Lesson 28 – Defer,Panic & Recover | Dataplexa

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:

  1. Function executes
  2. Panic occurs
  3. Deferred functions execute
  4. 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 defer for cleanup
  • Use panic only for unrecoverable states
  • Use recover at 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.