defer的使用
defer是什么
defer 是一个关键字,它后面跟的语句,在它所属的函数里面,会被延迟执行。
因为其延迟执行的特性,所以很适合在函数执行结束后,释放一些打开的资源句柄,比如关闭文件,释放mysql实例,redis并发解锁等等。
有多个defer的执行顺序
defer 把要执行的语句,依次放入栈中,采取先进后出方式,可以理解为往一个瓶子中放东西,先进去的东西在底部,倒出来时,最后出来。
看例子:
func main() {
fmt.Println("111")
defer fmt.Println("01")
defer fmt.Println("02")
fmt.Println("222")
}
// 输出结果
111
222
02
01
执行时机
- 确定返回值(给返回值赋值)
- 运行defer
- ret指令
问题,下面的代码输出什么?
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
}
我们来逐步分析:
1. 执行到第一个 defer 时,会先执行 calc("A", x, y) -> calc("A", 1, 2)
2. 执行 calc("A", 1, 2) 时,里面会打印 "A" 1 2 3
3. 此时第一defer就是 defer calc("AA", 1, 3),然后放入栈中
4. 继续执行 x = 10
5. 继续执行第二个defer,此时先执行 calc("B", x, y) -> calc("B", 10, 2)
6. 执行 calc("B", 10, 2) 时,会打印 "B" 10 2 12
7. 此时第二个defer就是 defer calc("BB", 10, 12) ,也放入栈中
8. 执行 y = 20
9. main返回时,执行第二个defer时,输出 "BB" 10 12 22
10. 执行第二个defer,输出 "AA" 1 3 4
所以最终输出结果是:
A 1 2 3
B 10 2 12
BB 10 12 22
AA 1 3 4
本作品采用《CC 协议》,转载必须注明作者和本文链接