如何拆解延迟语句
如果 defer 像前面介绍的那样简单,这个世界就完美了。但事情总是没这么简单,defer 用得 不好,会陷入泥潭。
避免陷入泥潭的关键是必须深刻理解下面这条语句:
return xxx
1
上面这条语句经过编译之后,实际上生成了三条指令:
1)返回值 = xxx。
2)调用 defer 函数。
3)空的 return。
第 1 和第 3 步是 return 语句生成的指令,也就是说 return 并不是一条原子指令;第 2 步是 defer 定义的语句,这里可能会操作返回值,从而影响最终结果。
下面来看两个例子,试着将 return 语句和 defer 语句拆解到正确的顺序。
第一个例子:
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
1
2
3
4
5
6
7
2
3
4
5
6
7
拆解后:
func f() (r int) {
t := 5
// 1. 赋值指令
r = t
// 2. defer 被插入到赋值与返回之间执行,这个例子中返回值 r 没被修改过
func() {
t = t + 5
}
// 3. 空的 return 指令
return
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
这里第二步实际上并没有操作返回值 r,因此,main 函数中调用 f () 得到 5。
第二个例子:
func f2() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
1
2
3
4
5
6
2
3
4
5
6
拆解后:
func f() (r int) {
// 1. 赋值
r=1
// 2. 这里改的 r 是之前传进去的 r,不会改变要返回的那个 r 值
func(r int) {
r=r + 5
}(r)
// 3. 空的 return
return
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
第二步,改变的是传值进去的 r,是形参的一个复制值,不会影响实参 r。因此,main 函数中需要调用 f () 得到 1。
上次更新: 5/9/2023, 10:58:32 AM