Defer Panic Recover

Back

Loading concept...

🪂 Go’s Safety Net: Defer, Panic & Recover

Imagine you’re a tightrope walker with a safety net below. No matter what tricks you try up there, the net catches you if you fall. That’s exactly what Go gives you with defer, panic, and recover.


🎪 The Big Picture

Think of running a program like performing in a circus:

  • Defer = Your cleanup crew that ALWAYS shows up after your act
  • Panic = When something goes terribly wrong (you fall!)
  • Recover = The safety net that catches you

Let’s meet each one!


📋 Defer Statement

What is Defer?

Defer is like making a promise: “Before I leave this room, I WILL turn off the lights.”

When you use defer, you’re telling Go: “Run this later, right before the function ends.”

func visitRoom() {
    defer fmt.Println("Lights off!")
    fmt.Println("Doing work...")
    fmt.Println("More work...")
}
// Output:
// Doing work...
// More work...
// Lights off!

Why Use Defer?

Imagine opening a treasure chest (a file). You MUST close it when done, or bad things happen!

func readTreasure() {
    file := openChest()
    defer closeChest(file) // Promise made!

    // Read treasure...
    // Even if something breaks here,
    // the chest WILL be closed!
}

Key Point: The deferred action runs even if your function crashes!


📚 Defer Stack (LIFO Order)

The Stack of Promises

What if you make multiple promises? They stack up like plates!

Last In, First Out = The last promise you make is the first one kept.

func stackExample() {
    defer fmt.Println("First promise")
    defer fmt.Println("Second promise")
    defer fmt.Println("Third promise")
    fmt.Println("Doing work!")
}

Output:

Doing work!
Third promise   ← Last in
Second promise  ← Second
First promise   ← First in, last out

Real-World Example: Stacking Plates

graph TD A["🍽️ Put Plate 1"] --> B["🍽️ Put Plate 2"] B --> C["🍽️ Put Plate 3"] C --> D["Take Plate 3 first!"] D --> E["Take Plate 2"] E --> F["Take Plate 1 last"]

The plate you put on TOP comes off FIRST!

Arguments Are Captured Immediately

Here’s a tricky part! When you defer, the VALUES are saved right then:

func trickQuestion() {
    x := 10
    defer fmt.Println("x is:", x)
    x = 20
    fmt.Println("Changed x to 20")
}
// Output:
// Changed x to 20
// x is: 10  ← Captured when defer was called!

💥 Panic

What is Panic?

Panic is Go screaming: “EMERGENCY! I can’t continue!”

It’s like a fire alarm—everything stops, and everyone evacuates!

func ohNo() {
    fmt.Println("Starting...")
    panic("Something terrible happened!")
    fmt.Println("This never runs")
}

When Does Panic Happen?

  1. You call it yourself:
panic("Oops!")
  1. Go panics automatically:
// Dividing by zero
result := 10 / 0  // PANIC!

// Accessing nil
var p *int
*p = 5  // PANIC!

// Out of bounds
arr := []int{1, 2, 3}
arr[100] = 5  // PANIC!

What Happens During Panic?

graph TD A["😱 Panic Occurs!"] --> B["Stop current function"] B --> C["Run all deferred functions"] C --> D["Go up to caller function"] D --> E["Run its deferred functions"] E --> F["Keep going up..."] F --> G["Program crashes with error"]

Important: Even during panic, deferred functions still run!

func panicDemo() {
    defer fmt.Println("Cleanup happens!")
    panic("Disaster!")
}
// Output:
// Cleanup happens!   ← Defer runs first!
// panic: Disaster!

🦸 Recover

What is Recover?

Recover is your superhero! It catches panics and stops the crash.

It’s like catching a falling glass before it shatters.

Rule: recover() only works INSIDE a deferred function!

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Caught panic:", r)
        }
    }()

    panic("Falling!")
    // This line never runs
}

func main() {
    safeFunction()
    fmt.Println("Program continues!")
}
// Output:
// Caught panic: Falling!
// Program continues!   ← No crash!

The Recovery Pattern

Here’s the standard pattern you’ll see everywhere:

func doRiskyThing() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered: %v", r)
        }
    }()

    // Risky code here...
    panic("boom!")

    return nil
}

Recover Only Works in Defer!

This WON’T work:

func broken() {
    if r := recover(); r != nil {
        // This never catches anything!
    }
    panic("oops")
}

This WILL work:

func working() {
    defer func() {
        if r := recover(); r != nil {
            // This catches the panic!
        }
    }()
    panic("oops")
}

🎯 Putting It All Together

The Complete Safety Net

func riskyCircusAct() {
    // Our safety net
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("🦸 Caught you!", r)
        }
    }()

    // Cleanup promises (LIFO order)
    defer fmt.Println("3️⃣ Clean equipment")
    defer fmt.Println("2️⃣ Thank audience")
    defer fmt.Println("1️⃣ Bow")

    fmt.Println("🎪 Starting act...")
    fmt.Println("🤸 Doing backflip...")
    panic("😱 Lost balance!")
    fmt.Println("This never happens")
}

Output:

🎪 Starting act...
🤸 Doing backflip...
1️⃣ Bow
2️⃣ Thank audience
3️⃣ Clean equipment
🦸 Caught you! 😱 Lost balance!

Flow Diagram

graph TD A["Start Function"] --> B["Set up defer with recover"] B --> C["Set up other defers"] C --> D["Run main code"] D --> E{Panic?} E -->|No| F["Normal return"] E -->|Yes| G["Run defers in reverse"] G --> H{Recover called?} H -->|Yes| I["Continue program"] H -->|No| J["Crash!"] F --> K["Run defers in reverse"] K --> L["Function ends"]

⚠️ When to Use What

Situation Use This
Close files/connections defer
Unlock mutexes defer
Something truly broken panic
Web server request handler recover
Library boundaries recover

Don’t Overuse Panic!

// ❌ BAD - Don't panic for normal errors
func findUser(id int) *User {
    if id < 0 {
        panic("bad id") // Too extreme!
    }
}

// ✅ GOOD - Return an error instead
func findUser(id int) (*User, error) {
    if id < 0 {
        return nil, errors.New("bad id")
    }
}

Rule of Thumb: Use panic only when your program CANNOT safely continue.


🎉 Summary

Concept What It Does Analogy
Defer Schedules code to run later “Clean up after yourself” promise
Defer Stack Multiple defers run in reverse Stack of plates
Panic Emergency stop Fire alarm
Recover Catches panics Safety net

You now have Go’s complete safety toolkit! 🛡️

Remember:

  • Defer = Always clean up
  • Panic = Only for emergencies
  • Recover = Only inside defer

Go forth and write safe Go code! 🚀

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.