defer
is very useful in control. It is used within a function.
If a function contains one or multiple defer
command, it will not really return or finish unless all the functions followed directly by defer
have finished. All the functions are called 'delayed' functions if they are on the right side of defer
. You can release the resources using defer
right after requesting it, in case you forget to release at the end of a function.
If the defer
function has some input arguments, the input expressions will be calculated directly. But the defer
function will not be executed immediately.
package main
import (
"fmt"
)
func mixed(n,m int) (number int) {
fmt.Println("step mixed")
return n+m
}
func modify(n int) (number int) {
defer func (plus int) (result int) {
fmt.Println("Coming in defer")
result = n + plus
number += result
fmt.Println(number)
return
}(mixed(1,2))
fmt.Println("step 1", number)
number++
fmt.Println("step 2", number)
return
}
func main() {
modify(2)
}
The output is shown as below:
go run defer_learn.go
step mixed
step 1 0
step 2 1
Coming in defer
6
Let's see another example.
func printNumbers() {
for i:=0; i<5; i++ {
defer fmt.Printf("%d", i)
}
}
The result is: 43210
not 01234
because this for loop can translate into the following statements:
fmt.Printf("%d",0)
fmt.Printf("%d",1)
fmt.Printf("%d",2)
fmt.Printf("%d",3)
fmt.Printf("%d",4)
When the function printNumbers
wants to finish, it executes all defer
statements using FIFO
mode. So the output is 43210
.
If we change the defer
statement a little into this:
func printNumbers() {
for i:=0; i<5; i++ {
defer func() {
fmt.Printf("%d", i)
}()
}
}
The result is 55555
because defer
function doesn't have input argument, so it has nothing to calculate before really execution. There will be 5 fmt.Printf("%d", i)
listing before printNumbers
finishes where i=5
at this point of time.