网站首页 返回列表 像“草根”一样,紧贴着地面,低调的存在,冬去春来,枯荣无恙。

Golang defer总结

2020-06-10 04:12:13 admin 1098

0

Golang有一个特殊的控件语句,那就是defer,defer语句用于延迟调用指定的函数,比如释放资源等,它会在函数最后执行,但在return之前,先让我们看代码简单了解下:

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. println("test1")
  7. defer func() {
  8. println("defer test2")
  9. }()
  10. println("test3")
  11. }

执行结果如下:

__

  1. test1
  2. test3 defer test2

很清楚地看到,有defer那个函数最后才执行的

现在改一下代码,让代码panic,当抛出异常时,defer延迟函数还会执行吗?

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. println("test1")
  7. panic("panic")
  8. defer func() {
  9. println("defer test2")
  10. }()
  11. println("test3")
  12. }

输出

__

  1. test1 panic: panic
  2. Process finished with exit code 2

延迟函数居然没有执行,为什么会这样呢?是因为panic在延迟函数之前了,再改一下代码如下

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. println("test1")
  7. defer func() {
  8. println("defer test2")
  9. }()
  10. panic("panic")
  11. println("test3")
  12. }

输出

__

  1. test1 defer test2
  2. panic: panic

延迟函数执行了,可以看到panic在延迟函数之前延迟函数是执行不了的,毕竟抛出异常。

1

再看一个例子

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. for i:=0;i<5 ;i++ {
  7. defer func() {
  8. println(i)
  9. }()
  10. }
  11. }

输出

__

  1. 5
  2. 5
  3. 5
  4. 5
  5. 5
  6. Process finished with exit code 0

是不是觉得很惊诧啊,是的,为什么不是0 1 2 3 4 啊?
这正是因为延迟函数执行时机引起的,当println(i)时,i已经是5了,跳出了for循环,如果延迟函数要使用外部的变量应该通过参数传入,看下面

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. for i := 0; i < 5; i++ {
  7. defer func(i int) {
  8. println(i)
  9. }(i)
  10. }
  11. }

输出

__

  1. 4
  2. 3
  3. 2
  4. 1
  5. 0
  6. Process finished with exit code 0

对了吧,哎哎哎,不对啊,怎么反过来了?
其实延迟函数是一个栈,先进后出最后放进去的最后出来,我们再试一个是不是这样

__

  1. package main
  2. func main() {
  3. test()
  4. }
  5. func test() {
  6. defer func() {
  7. println("test1")
  8. }()
  9. defer func() {
  10. println("test2")
  11. }()
  12. }

输出

__

  1. test2
  2. test1
  3. Process finished with exit code 0

果真如此。

2.总结

看了上边的例子,最后我们总结一下,学过的东西如果不好好总结,会很快忘记的,打算以后看的书都全部写出来,这样书才没有白读啊
我们规定一下,上边test()方法为外围函数,调用test()的叫调用函数,调用与被调用区分开,总结如下

  1. 当外围函数正常执行完毕时,只有其中的延迟函数都执行完毕时,外围函数才会真正执行完
  2. 当外围函数执行return时,只有延迟函数全都执行完时,才会真正地返回
  3. panic在延迟函数后边,只有延迟函数执行完毕时,panci才会扩散到调用函数
  4. 延迟函数总是会在外围函数执行前执行,除非延迟函数前面已经panic了
  5. defer语句在外围函数的函数体中位置不限,数量不限
  6. 如果延迟函数要使用外部的变量应该通过参数传入
  7. 迟延函数是一个栈,先进后出
转载文章,原文链接: Golang defer总结

关键字词golangdefer

分享到:

如需留言,请 登录,没有账号?请 注册

0 条评论 0 人参与

顶部 底部