Golang defer总结

作者: 想入飞飞___ | 来源:发表于2017-12-23 15:24 被阅读40次

    0

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

    package main
    
    func main() {
        test()
    }
    func test() {
        println("test1")
        defer func() {
            println("defer test2")
        }()
        println("test3")
    }
    
    
    

    执行结果如下:

    test1
    test3
    defer test2
    

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

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

    package main
    
    func main() {
        test()
    }
    func test() {
    
        println("test1")
            panic("panic")
        defer func() {
            println("defer test2")
        }()
        
        println("test3")
    }
    

    输出

    test1
    panic: panic
    
    Process finished with exit code 2
    
    

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

    package main
    
    func main() {
        test()
    }
    func test() {
    
        println("test1")
    
        defer func() {
            println("defer test2")
        }()
        panic("panic")
        println("test3")
    }
    
    

    输出

    test1
    defer test2
    panic: panic
    
    

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

    1

    再看一个例子

    package main
    
    func main() {
       test()
    }
    func test() {
    
       for i:=0;i<5 ;i++  {
           defer func() {
               println(i)
           }()
       }
    }
    

    输出

    5
    5
    5
    5
    5
    
    Process finished with exit code 0
    
    

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

    package main
    
    func main() {
        test()
    }
    func test() {
    
        for i := 0; i < 5; i++ {
            defer func(i int) {
                println(i)
            }(i)
        }
    }
    
    

    输出

    4
    3
    2
    1
    0
    
    Process finished with exit code 0
    

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

    package main
    
    func main() {
        test()
    }
    func test() {
    
         defer func() {
            println("test1")
         }()
         defer func() {
            println("test2")
         }()
    }
    
    

    输出

    test2
    test1
    Process finished with exit code 0
    

    果真如此。

    2.总结

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

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

    相关文章

      网友评论

        本文标题:Golang defer总结

        本文链接:https://www.haomeiwen.com/subject/hocqgxtx.html