Go Defer in Depth
Defer in depth is the set of rules that fix when a deferred call runs and what values it sees. A deferred call runs when its enclosing function returns.
Deferred arguments are read at defer time
The defer line reads n while it is still 10. The later change to 99 does not reach the deferred call.
package main
import "fmt"
func main() {
n := 10
defer fmt.Println(n)
n = 99
fmt.Println(n)
}Three defers run last-in first-out
Three calls are deferred in order. They run in the reverse order at the end.
package main
import "fmt"
func main() {
defer fmt.Println("first deferred")
defer fmt.Println("second deferred")
defer fmt.Println("third deferred")
fmt.Println("main work")
}A deferred closure changes a named return value
price names its result total. The deferred literal adds 25 to total before the caller reads it.
package main
import "fmt"
func price() (total int) {
total = 100
defer func() {
total += 25
}()
return total
}
func main() {
fmt.Println(price())
}Example
package main
import "fmt"
func report() {
fmt.Println("start")
defer fmt.Println("end")
fmt.Println("work one")
fmt.Println("work two")
}
func main() {
report()
fmt.Println("done")
}Key points
- The arguments of a deferred call are read when the defer line runs.
- Deferred calls run in last-in first-out order.
- Last-in first-out means the last deferred call runs first.
- A deferred function literal runs at return time.
- A deferred literal reads the current values of the variables it captures.
- A named result is a result declared with a name in the function signature.
- A deferred literal can change a named result before the caller sees it.
In this example, report prints start first. The defer line sets the end print aside. The two work lines print next. The deferred end line prints when report returns. Main then prints done.
Note
Deferred calls still run when a function returns early with an error.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Go Playground
Exercise
A function defers print A, then print B, then print C. Which deferred line prints first?