Defer execution order in Go - Time & Space Complexity
When using defer in Go, it's important to know how the order of deferred calls affects program steps.
We want to see how the number of deferred calls impacts the total work done when the function ends.
Analyze the time complexity of the following code snippet.
func example(n int) {
for i := 0; i < n; i++ {
defer func(x int) {
println(x)
}(i)
}
}
This code defers printing numbers from 0 to n-1, storing each deferred call during the loop.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop runs n times, each time adding one deferred function call.
- How many times: Exactly n deferred calls are stacked.
Each loop adds one deferred call, and at the end, all deferred calls run in reverse order.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 deferred calls added and then 10 executed |
| 100 | 100 deferred calls added and then 100 executed |
| 1000 | 1000 deferred calls added and then 1000 executed |
Pattern observation: The total work grows linearly with n because each deferred call is stored and later executed once.
Time Complexity: O(n)
This means the total steps grow in a straight line as the number of deferred calls increases.
[X] Wrong: "Deferred calls run immediately or only once at the end without extra cost."
[OK] Correct: Deferred calls are stacked during execution and all run later, so the total work includes both stacking and running each deferred call.
Understanding how defer stacks calls and affects execution helps you reason about function cleanup and resource management in real programs.
"What if we replaced defer with immediate function calls inside the loop? How would the time complexity change?"
Practice
defer statements are used in a Go function?Solution
Step 1: Understand defer behavior
In Go, deferred functions are postponed until the surrounding function returns.Step 2: Execution order of deferred calls
Deferred calls run in reverse order of their appearance, like a stack (last-in, first-out).Final Answer:
Deferred calls execute in last-in, first-out order when the function returns. -> Option AQuick Check:
Defer order = last-in, first-out [OK]
- Thinking defer calls run immediately
- Assuming defer calls run in code order
- Believing defer calls never run
Solution
Step 1: Recall defer syntax
The keyworddeferis followed directly by the function call without assignment or parentheses around defer.Step 2: Identify correct syntax
defer fmt.Println("Hello") correctly usesdefer fmt.Println("Hello"). Other options misuse defer syntax.Final Answer:
defer fmt.Println("Hello") -> Option CQuick Check:
defer + function call = correct syntax [OK]
- Adding := after defer
- Using parentheses after defer keyword
- Writing extra words like 'call' after defer
package main
import "fmt"
func main() {
defer fmt.Println("First")
defer fmt.Println("Second")
fmt.Println("Third")
}Solution
Step 1: Identify immediate and deferred prints
"Third" is printed immediately. The two deferred prints run after main ends.Step 2: Determine deferred call order
Deferred calls run last-in, first-out, so "Second" prints before "First".Final Answer:
Third Second First -> Option BQuick Check:
Immediate then deferred reverse order = Third, Second, First [OK]
- Assuming deferred prints run in code order
- Thinking deferred prints run before immediate prints
- Confusing the order of deferred calls
func example() {
defer fmt.Println("A")
defer fmt.Println("B")
defer fmt.Println("C")
fmt.Println("D")
}
If the output is not as expected, what is the likely mistake?Solution
Step 1: Understand expected output order
"D" should print first immediately, then deferred calls print "C", "B", "A" in reverse order.Step 2: Identify cause of unexpected output
If "D" is missing or not printed before defers, output order changes unexpectedly.Final Answer:
The function does not call fmt.Println("D") before defers. -> Option AQuick Check:
Immediate prints must run before deferred calls [OK]
- Expecting deferred calls to run in code order
- Forgetting to call immediate print before defers
- Misunderstanding when deferred calls execute
Solution
Step 1: Understand defer closing order
Deferred calls run last-in, first-out, so the last deferred closes first.Step 2: Apply to file closing
Deferring file1.Close() first, then file2.Close(), then file3.Close() means file3 closes first, then file2, then file1, matching open order reversed.Final Answer:
defer file1.Close() defer file2.Close() defer file3.Close() -> Option DQuick Check:
Defer in open order closes files in reverse [OK]
- Deferring closes in reverse order of opening
- Calling Close() immediately without defer
- Using incorrect function calls for closing
Ready to prove it?
Pass the test and this pattern moves unknown
