• golang中defer的详解 转自https://blog.csdn.net/skh2015java/article/details/77081250


    Go里的defer很有用,尤其在很多执行模块化操作时,初始化时给各个需要执行的模块传入参数,但是这些参数有些事在模块执行过程中才赋值的。

    这时候有了defer就不会把代码写的很凌乱。

    Go的defer语句用来调度一个函数调用(被延期的函数),使其在执行defer的函数即将返回之前才被运行,被延期执行的函数,它的参数(包括接受者)实在defer执行的时候被求值的,而不是在调用执行的时候。也就是说被延期执行的函数的参数是按正常顺序被求值的。

        defer会按逆序执行

        defer是Go语言提供的关键字,常用来释放资源,会在函数返回之前进行调用。如果有多个defer表达式,调用顺序类似于栈,越后面的defer表达式越先被调用。defer 函数调用的执行时机是外层函数设置返回值之后, 并且在即将返回之前。

    例1:

    func main() {
             for i:=0 ;i<5;i++{
                  defer fmt.Printf("%d",i)
                  fmt.Println("bbbbb")
             }
             fmt.Println("aaaaa")
    }

    执行结果:

    bbbbb

    bbbbb

    bbbbb

    bbbbb

    bbbbb

    aaaaa

    43210

    例2:

    func trace(s string) string {
           fmt.Println("entering:",s)
           return s
    }

    func un(s string) {
           fmt.Println("leaving:",s)
    }

    func a() {
           defer un(trace("a"))
           fmt.Println("in a")
    }

    func b() {
           defer un(trace("b"))
           fmt.Println("in b")
           a()
    }

    func main() {
           b()
    }

    执行结果如下:

    entering: b

    in b

    entering: a

    in a

    leaving: a

    leaving: b

     例3

    func f1() (result int) {
           defer func() {
                  result++
           }()
           return 0
    }

    func f2() (r int) {
           t := 5
           defer func() {
                  t = t+5
           }()
           return t
    }


    func f3() (t int) {
           t = 5
           defer func() {
                  t = t+5
           }()
           return t
    }


    func f4() (r int) {
           defer func(r int) {
                  r = r + 5
           }(r)
           return 1
    }

    要使用defer不踩坑,最重要的一点就是明白,return xxx不是一条原子指令

    函数返回的过程是这样子的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中。

    defer表达式可能会在设置函数返回值之后,在返回到调用函数之前,修改返回值,使最终的函数返回值与你想象的不一致。

    可以将return xxx改成

    返回值=xxx

    调用defer函数

    空的return

    例3可以改写成这样

    func f11() (result int) {
           result = 0   //先给返回值赋值
           func(){               //再执行defer 函数
                  result++
           }()
           return                //最后返回
    }

    func f22() (r int) {
           t := 5
           r = t //赋值指令
           func(){   //defer 函数被插入到赋值与返回之间执行,这个例子中返回值r没有被修改
                  t = t+5
           }
           return   //返回
    }

    func f33() (t int) {
           t = 5    //赋值指令
           func(){
                  t = t+5  //然后执行defer函数,t值被修改
           }
           return
    }

    func f44() (r int) {
           r = 1    //给返回值赋值
           func(r int){   //这里的r传值进去的,是原来r的copy,不会改变要返回的那个r值
                  r = r+5
           }(r)
           return
    }

    参考:《Effective Go》、《深入解析go内核实现》

  • 相关阅读:
    Robotium 测试方法
    T-SQL—理解CTEs
    SQLServer复制(二)--事务代理作业
    数据库复制(一)--复制介绍
    小议如何使用APPLY
    优化SQLServer——表和分区索引(二)
    关于UNPIVOT 操作符
    XML 在SQLServer中的使用
    列存储索引1:初识列存储索引
    T-SQL性能调整(一)--编译和重新编译
  • 原文地址:https://www.cnblogs.com/si812cn/p/9565621.html
Copyright © 2020-2023  润新知