golang关键字defer使用

defer关键词规则

  • 规则一:延迟函数的参数在defer语句出现时就已经确定下来了(因为会有拷贝)
  • 规则二:延迟函数执行按后进先出顺序执行,即先出现的defer最后执行(filo,栈操作)
  • 规则三:延迟函数可能操作主函数的”具名”返回值
    • 对于指针类型参数,规则仍然适用,只不过延迟函数的参数是一个地址值,
    • 这种情况下,defer后面的语句对变量的修改可能会影响延迟函数。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
func variableDemo1() {
for i := 1; i <= 5; i++ {
//i会进行一次拷贝到t,所以能正常打印数据
defer func(t int) {
fmt.Printf("t = %d \n", t)
}(i)

//这里只会输出6,因为i在defer已经执行完循环,i指向都是最终值
defer func() {
fmt.Printf("t2 = %d \n", i)
}()
}
}

//返回前执行defer,此时t=2,++后返回3
func returnVariableDemo1() (t int) {
defer func() {
t++
}()
return 2
}

//返回前执行defer,但是无法赋值结果,无返回t变量,返回的是2
func returnVariableDemo2() int {
t := 2
defer func() {
t++
}()
return t
}

func variableDemo2() (t int) {
//这里传入的t是初始值只0,defer开始时就拷贝0到i,第二个输出t是ret前赋值为2,所以是2
defer func(i int) {
fmt.Println("variableDemo2 i = ", i) // 0
fmt.Println("variableDemo2 t = ", t) // 2
}(t)
t = 1
return 2
}