• defer后面如果是普通的函数调用, 那函数的参数在执行到defer的时候就已经确定了
  • defer后面如果是闭包, 闭包内部直接使用外部变量, 那么真正执行这个闭包的时候才会读取变量的当前值
  • 执行到defer的时候, defer函数调用的函数值和参数会立刻求值并保存, 函数体延迟到当前函数返回前执行
1
2
3
4
5
6
7
8
9
10
func main() {
fmt.Println(test1())
fmt.Println(test2())
fmt.Println(test3())
fmt.Println(test4())
}
func test1() (v int) {
defer fmt.Println(v)
return v
}

进入defer的时候, Println没有执行, 但是v已经确定了
打印0 0

1
2
3
4
5
6
func test2() (v int) {
defer func() {
fmt.Println(v)
}()
return 3
}

这里和test1的区别就是Println在闭包里面, 因为v是命名返回值,return 3等效于v = 3 , return, 所以闭包打印3, 然后函数返回3, main再打印一次

1
2
3
4
5
func test3() (v int) {
defer fmt.Println(v)
v = 3
return 4
}

这里一开始v = 0, 所以defer的时候就已经确定了, 后面v变成什么都不影响了, 所以先打印defer 0, 然后返回值是4, 打印4

1
2
3
4
5
6
func test4() (v int) {
defer func(n int) {
fmt.Println(n)
}(v)
return 5
}

这里defer函数虽然是闭包, 但是里面有参数n, 而调用的时候是(v)
参数会立刻保存, v = 0, 于是在返回前, defer打印0, 函数返回5, main打印5