How does the defer statement work and in what order do deferred calls run?
Learn how Go's defer statement works: when deferred calls run, LIFO execution order, argument evaluation timing, and idiomatic cleanup patterns.
Expected Interview Answer
A defer statement schedules a function call to run just before the surrounding function returns, and multiple deferred calls execute in last-in, first-out (LIFO) order.
When defer is reached, the deferred function's arguments are evaluated immediately, but the call itself is pushed onto a stack and runs only as the enclosing function exits — whether by a normal return, a panic, or an early return. Because they pop in LIFO order, the last defer registered runs first. A deferred closure can also read and modify named return values, which is why defer is commonly used for cleanup like closing files, unlocking mutexes, and recovering from panics.
- Guarantees cleanup runs on every exit path
- Keeps resource acquisition and release visually close
- Runs even when the function panics
- LIFO order naturally unwinds nested resources
- Can adjust named return values before returning
AI Mentor Explanation
defer is like a captain giving end-of-innings instructions the moment each fielder takes position — collect the cones, sign the scorebook — but they only act when the innings actually ends. The last instruction given is honoured first, like players nearest the pavilion leaving first. Whether the innings ends by all-out or declaration, those closing duties still run, exactly as deferred cleanup runs on any exit path.
Step-by-Step Explanation
Step 1
Reach the defer
When execution hits a defer statement, the call is registered for later.
Step 2
Evaluate arguments now
The deferred function's arguments are evaluated immediately, capturing their values at that point.
Step 3
Push onto a stack
The deferred call is pushed onto the function's defer stack rather than executed.
Step 4
Function begins to exit
On return or panic, Go pops the defer stack and runs the calls in LIFO order.
Step 5
Adjust return values
A deferred closure can read or modify named return values before the function actually returns.
What Interviewer Expects
- That deferred calls run at function exit, not immediately
- LIFO ordering of multiple defers
- Arguments are evaluated when defer executes, not when the call runs
- Common uses: closing files, unlocking mutexes, recover
- That deferred closures can modify named return values
Common Mistakes
- Thinking arguments are evaluated when the deferred call runs, not when defer is reached
- Assuming defers run in the order written instead of reverse
- Deferring inside a loop and exhausting resources before the function returns
- Expecting a deferred call to run at end of a block scope rather than end of the function
- Ignoring the error returned by a deferred Close
Best Answer (HR Friendly)
“The defer keyword in Go tells the program to run a piece of cleanup code right before the current function finishes, no matter how it finishes. If you defer several things, they run in reverse order, which makes it easy to tidy up resources like open files safely.”
Code Example
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
defer fmt.Println("deferred:", i) // i captured at defer time
}
fmt.Println("function body done")
// Output:
// function body done
// deferred: 2
// deferred: 1
// deferred: 0
}package main
import (
"fmt"
"os"
)
func readFile(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // runs on every return path
buf := make([]byte, 64)
n, err := f.Read(buf)
if err != nil {
return err
}
fmt.Printf("read %d bytes\n", n)
return nil
}Follow-up Questions
- When are the arguments of a deferred call evaluated?
- How can a deferred function change a named return value?
- Why can deferring inside a loop be problematic?
- How does defer behave when the surrounding function panics?
- What is the performance cost of defer and when might it matter?
MCQ Practice
1. In what order do multiple deferred calls execute?
Deferred calls pop off a stack, so the last one registered runs first (LIFO).
2. When are the arguments to a deferred function evaluated?
Arguments are evaluated immediately at the defer statement; only the call is postponed.
3. When does a deferred call run?
Deferred calls run as the enclosing function exits, on both normal returns and panics.
Flash Cards
When does a deferred call run? — Just before the surrounding function returns, on any exit path including panic.
In what order do multiple defers run? — LIFO — the last deferred call runs first.
When are deferred arguments evaluated? — Immediately when the defer statement is reached, not when the call runs.
A common use of defer? — Cleanup: closing files, unlocking mutexes, and calling recover.