What does this snippet with two parameterized deferred closures print, and in what order?
Read the snippet below. Two deferred closures each take a parameter val, and a is reassigned between the two defer statements.
func deferExample() int {
a := 10
defer func(val int) {
fmt.Println("first:", val)
}(a)
a = 20
defer func(val int) {
fmt.Println("second:", val)
}(a)
a = 30
fmt.Println("exiting:", a)
return a
}
Predict the output.
It prints exiting: 30, second: 20, first: 10. A deferred call's arguments are evaluated at the defer statement, so (a) snapshots a's value — 10, then 20 — and the later a = 30 cannot change them. Deferred calls run in LIFO order.
- ✗Assuming a deferred closure's parameter is evaluated when the call runs rather than at the
deferstatement - ✗Expecting the deferred calls in registration order, so printing
firstbeforesecond - ✗Thinking the final
a = 30overrides the values already snapshotted into the deferred calls
- →How would the output change if the closures read
adirectly instead of taking avalparameter? - →Why does
exiting: 30print before any of the deferred lines?
What does this print?
func deferExample() int {
a := 10
defer func(val int) {
fmt.Println("first:", val)
}(a)
a = 20
defer func(val int) {
fmt.Println("second:", val)
}(a)
a = 30
fmt.Println("exiting:", a)
return a
}
Output
exiting: 30
second: 20
first: 10
Why
The key subtlety is that a deferred call's arguments are evaluated at the defer statement, even when the call is a closure with parameters. The (a) at the end of each defer is an ordinary argument pass and is evaluated right away:
- the first
defersnapshotsval = 10(at that pointa == 10); - the second
defersnapshotsval = 20(by thena == 20).
The later a = 30 does not touch the captured values — they were copied and stored alongside the deferred calls.
The function body runs first, so exiting: 30 prints first. Then, at return, the deferred calls run in LIFO order (last registered runs first), so second: 20 comes before first: 10.