What does this snippet print, and why does wrapping the call in a closure change it?
Read the snippet below. A defer fmt.Println(a) is registered before a is reassigned.
Determine what it prints, and explain why wrapping the call in a closure — defer func(){ fmt.Println(a) }() — would change the result.
func main() {
var a int
defer fmt.Println(a)
a = 20
}
Predict the output.
It prints 0. defer evaluates its arguments at the defer statement, capturing a's value (0) then; the later a = 20 does not affect it. Wrap it as defer func(){ fmt.Println(a) }() and the closure reads a at return, printing 20.
- ✗Assuming
deferevaluates its arguments at function return rather than at registration - ✗Believing the closure form captures
aby value at thedeferstatement instead of reading it at return - ✗Confusing argument evaluation timing with the LIFO execution order of deferred calls
- →If you
defera method call on a pointer, when is the receiver evaluated? - →How does a
deferinside aforloop interact with the loop variable?
What does this print?
package main
import "fmt"
func main() {
var a int
defer fmt.Println(a)
a = 20
}
It prints 0. defer fmt.Println(a) evaluates the argument a at registration — at that moment a == 0. That value is copied and stored with the deferred call; the later a = 20 no longer affects it.
To print 20, wrap the call in a closure that takes no arguments:
func main() {
var a int
defer func() {
fmt.Println(a) // read at return → 20
}()
a = 20
}
The closure does not evaluate a at the defer statement — it captures the variable and reads its current value when it runs, i.e. at function return, when a is already 20.