美文网首页
golang defer && return

golang defer && return

作者: 大漠狼道 | 来源:发表于2016-05-15 23:59 被阅读733次

    defer中去修改函数中的变量时,会出现个小坑:
    修改函数中的变量会无效,如下面的函数a().

    /*
    func main() {
     k := a()
     fmt.Println("return:", k) // 打印结果为 return: 0
    }
    
    func a() int {
     var i int
     i = 0
     defer func() {
      i++
      fmt.Println("defer2:", i) // 打印结果为 defer: 2
     }()
     defer func() {
      i++
      fmt.Println("defer1:", i) // 打印结果为 defer: 1
     }()
     return i
    }
    */
    
    func main() {
     k := b()
     fmt.Println("return:", k) // 打印结果为 return: 2
    }
    
    func b() (i int) {
     defer func() {
      i++
      fmt.Println("defer2:", i) // 打印结果为 defer: 2
     }()
     defer func() {
      i++
      fmt.Println("defer1:", i) // 打印结果为 defer: 1
     }()
     i++
     return i // 或者直接 return 效果相同
    }
    
    /*
    func main() {
     fmt.Println("c return:", *(c())) // 打印结果为 c return: 2
    }
    
    func c() *int {
     var i int
     defer func() {
      i++
      fmt.Println("c defer2:", i) // 打印结果为 c defer: 2
     }()
     defer func() {
      i++
      fmt.Println("c defer1:", i) // 打印结果为 c defer: 1
     }()
     return &i
    }
    */
    

    有个概念先解释下:
    1.在有defer语句时,return语句并代表整个函数已退出
    2.在go文档中有这么句:
    Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usualand saved anew but the actual function is not invoked
    defer语句出现的地方,值和参数就已经赋值并更新,只不过函数没有被调用
    用栈来打个比方。defer函数在函数的栈底(相当有两个栈,defer栈和普通栈,defer栈存放defer函数,同时defer栈在return语句后),defer函数入栈时,会带上相应的环境.
    对于 A来说,
    return语句点i值确定了(0),defer不会也没办法改变其值,有点像函数的值传递,里面的值是无法改变外面的值的
    对于B来说,
    return语句点i确定为全局变量i,但是其值是不确定的,要等defer完了之后(既整个函数都执行完),才能确定.
    对于C来说,
    return语句点只确定了i的地址,值也是不确定的,要等defer完了之后(既整个函数都执行完),通过地址间接获取值

    汇编厉害的话,在编译后的汇编中也可以看到,
    a的话就是直接赋值,b的话就是全局变量,c会新建个object.
    而且defer语句出现的地方,会直接插入一个call runtime.deferproc(SB),也就是前面那句,"defer语句出现的地方,值和参数就已经赋值并更新".
    PS:我不懂汇编,自己通过对比汇编文件下理解出来的
    go tool compile -S XXX.go 可以获得

    相关文章

      网友评论

          本文标题:golang defer && return

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