02.defer延时调用
# 01.defer介绍
# 1.1 defer特性
- 1.关键字defer用于注册延迟调用。
- 2.这些调用直到return前才被执。因此,可以用来做资源清理。
- 3.多个defer语句,按先进后出的方式执行。
- 4.defer语句中的变量,在defer声明时就决定了。
# 1.2 defer用途
- 1.关闭文件句柄
- 2.锁资源释放
- 3.数据库连接释放
# 1.3 defer语句使用说明
- defer实现类似于栈,先进后出
- 而且是在函数执行完成到return返回之间调用
package main
import (
"fmt"
)
func main() {
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")
}
/*
start
end
3
2
1
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1.4 defer 执行时机
- 在 Go 语言的函数中 return 语句在底层并不是原子操作,它分为给返回值赋值和 RET 指令两步。
- 而 defer 语句执行的时机就在返回值赋值操作后,RET 指令执行前。
- 具体如下图所示:
# 1.5 defer案例
- defer 注册要延迟执行的函数时该函数所有的参数都需要确定其值
package main
import (
"fmt"
)
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}
/*
A 1 2 3
B 10 2 12
BB 10 12 22
AA 1 3 4
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 02.defer陷阱
# 2.1 defer 碰上闭包
- 也就是说函数正常执行,由于闭包用到的变量 i 在执行的时候已经变成4,所以输出全都是4
package main
import "fmt"
func main() {
var whatever [5]struct{}
for i := range whatever {
defer func() { fmt.Println(i) }()
}
}
/*
4
4
4
4
4
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上次更新: 2024/3/13 15:35:10