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

执行时机

  1. 确定返回值(给返回值赋值)
  2. 运行defer
  3. 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 协议》,转载必须注明作者和本文链接
六月的风
Junwind
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
躺平大叔 @ 躺平社区
文章
136
粉丝
15
喜欢
102
收藏
59
排名:274
访问:3.5 万
私信
所有博文
社区赞助商