zoukankan      html  css  js  c++  java
  • golang中defer使用小结

    golang语言中defer的使用场景较多,用于锁的关闭,连接的延迟关闭等,通常在函数的结束时调用,详细的讲就是在函数结束时返回值赋值后,返回前执行defer的方法,最后才返回,另外defer确实有一定的开销,拒绝滥用。

    第一点、defer 不带函数执行,defer可以理解像栈,先进后出,看下面代码

    func main() {
        defer fmt.Println("one")  //第一个进入
        defer fmt.Println("two")  //第二进入
        defer fmt.Println("three") //第三个进入
    }
    

    按照先进后出的规则输出

    three
    two
    one
    
    Process finished with exit code 0
    

    第二点、defer带函数的执行,defer执行在返回赋值后,返回前执行,看下面的列子

    下面的列子,我们定义 一个返回值res=1,然后返回(return)res时,赋值为7,根据我们所讲,defer函数执行在返回赋值后,返回前,那么此时res为7,defer 函数执行将res赋值为8,return最后返回应该为8
    看下面代码

    package main
    
    import "fmt"
    func main() {
        fmt.Println(test())
    }
    
    func test() (res int) {
        res = 1
        defer func() {
            fmt.Println("start", res)
            res++
            fmt.Println("end", res)
        }()
        return 7
    }
    
    

    执行结果:

    start 7
    end 8
    8
    
    Process finished with exit code 0
    

    第三点、defer 一定是延迟执行的么?答案是肯定的。但是有注意点需要注意

    看下面列子

    package main
    
    import "fmt"
    
    type SliceNum []int
    
    func NewSlice() SliceNum {
        return make(SliceNum, 0)
    
    }
    
    func (s *SliceNum) Add(elem int) *SliceNum {
        *s = append(*s, elem)
        fmt.Println("add", elem)
        fmt.Println("add SliceNum end", s)
        return s
    }
    func (s *SliceNum) test(elem int) *SliceNum {
        fmt.Println("test", elem)
        fmt.Println("test", s)
        return s
    }
    
    func main() {
        s := NewSlice()
        defer s.Add(1)
        s.Add(10)
    
    }
    
    

    输出结果:
    此时大家应该想到肯定是切片的加入顺序应该是10 然后 是1 结果也是这样

    add 10
    add SliceNum end &[10]
    add 1
    add SliceNum end &[10 1]
    
    Process finished with exit code 0
    

    读者客官可能会说,这太简单了,那么我们在defer 后面连续执行是什么效果呢?
    我们修改下main函数执行的方法如下:

    
    func main() {
        s := NewSlice()
        defer s.Add(1).Add(4)
        s.Add(11)
        s.Add(12)
        s.Add(13)
    }
    

    大家猜想下?可以先给个答案
    看下执行:

    add 1
    add SliceNum end &[1]
    add 11
    add SliceNum end &[1 11]
    add 12
    add SliceNum end &[1 11 12]
    add 13
    add SliceNum end &[1 11 12 13]
    add 4
    add SliceNum end &[1 11 12 13 4]
    
    Process finished with exit code 0
    
    此时defer后面的一个方法Add(1)先执行了,然后才执行的s.Add(11),s.Add(12),s.Add(13),最后才执行了Add(4)

    defer后面继续执行同样的方法或者其他方法呢?改变下我们的main函数如下:

    func main() {
        s := NewSlice()
        defer s.Add(1).Add(4).Add(100).test(200)
        s.Add(11)
        s.Add(12)
        s.Add(13)
    }
    

    这个执行结果又是怎么样的?
    看下结果吧:

    add 1
    add SliceNum end &[1]
    add 4
    add SliceNum end &[1 4]
    add 100
    add SliceNum end &[1 4 100]
    add 11
    add SliceNum end &[1 4 100 11]
    add 12
    add SliceNum end &[1 4 100 11 12]
    add 13
    add SliceNum end &[1 4 100 11 12 13]
    test 200
    test &[1 4 100 11 12 13]
    
    Process finished with exit code 0
    

    可以看到defer 中先执行的s.Add(1).Add(4).Add(100),然后执行s.Add(11), s.Add(12),s.Add(13),延迟执行的test函数,可以看到defer延迟执行的是最后的一个函数

    如何保证整个defer是在最后执行呢?当然可以了使用 defer fun(){
    }(),包住此方法

    修改下main函数

    func main() {
        s := NewSlice()
        defer func() {
            s.Add(1).Add(4).Add(100).test(200)
        }()//用func(){}()包住
        s.Add(11)
        s.Add(12)
        s.Add(13)
    }
    

    输出结果:

    add 11
    add SliceNum end &[11]
    add 12
    add SliceNum end &[11 12]
    add 13
    add SliceNum end &[11 12 13]
    add 1
    add SliceNum end &[11 12 13 1]
    add 4
    add SliceNum end &[11 12 13 1 4]
    add 100
    add SliceNum end &[11 12 13 1 4 100]
    test 200
    test &[11 12 13 1 4 100]
    
    Process finished with exit code 0
    

    此时,先执行s.Add(11),s.Add(12),s.Add(13),然后执行defer函数中的方法s.Add(1).Add(4).Add(100).test(200),最后输出已经按照我们想要的顺序执行了。

  • 相关阅读:
    路飞学城-Python开发集训-第1章
    Python制作的射击游戏
    使用百度地图API自动获取地址和经纬度
    使用高德地图JS获取当前位置和经纬度
    thinkphp5 使用PHPExcel 导入导出
    MySQL优化
    ABAP 新语法-实例讲解
    ASP.NET Core
    ASP.NET Core
    ASP.NET Core
  • 原文地址:https://www.cnblogs.com/show58/p/12421846.html
Copyright © 2011-2022 走看看