Go语言中defer和return执行顺序解析

1.首先明确return执行前都做了哪些事情。

    return是非原子性的,需要两步,执行前首先要得到返回值(为返回值赋值),return将返回值返回调用处。

2.defer、return、返回值之间的关系

测试用例1:无名返回值(即函数返回值为没有命名的返回值)

package main

import (
        "fmt"
)

func main() {
        fmt.Println("return:", Demo()) // 打印结果为 return: 0
}

func Demo() int {
        var i int
        defer func() {
                i++
                fmt.Println("defer2:", i) // 打印结果为 defer: 2
        }()
        defer func() {
                i++
                fmt.Println("defer1:", i) // 打印结果为 defer: 1
        }()
        return i
}

执行结果:

defer2 1 
defer1 2 
return: 0

测试用例2:有名返回值(函数返回值为已经命名的返回值)

package main

import (
        "fmt"
)

func main() {
        fmt.Println("return:", Demo2()) // 打印结果为 return: 2
}

func Demo2() (i int) {
        defer func() {
                i++
                fmt.Println("defer2:", i) // 打印结果为 defer: 2
        }()
        defer func() {
                i++
                fmt.Println("defer1:", i) // 打印结果为 defer: 1
        }()
        return i // 或者直接 return 效果相同
}

执行结果:

defer2 1 
defer1 2 
return: 2

结果分析:

从上面的测试用例可以看出,返回值,defer,return之间的执行顺序是:
先为返回值赋值,然后执行defer,然后return到函数调用处。

测试用例1 : 
实际上return 执行了两步操作。
因为返回值没有命名,所以return 之前
首先默认创建了一个临时零值变量(假设为s)作为返回值
然后将i赋值给s,此时s的值是0。后续的操作是针对i进行的,
所以不会影响s, 此后因为s不会更新,
所以return s 不会改变
    相当于:
          var i int
          s := i
          return s
测试用例2:
因为返回值已经提前定义了,不会产生临时零值变量,
返回值就是提前定义的变量,后续所有的操作也都是基于已经定义的变量,
任何对于返回值变量的修改都会影响到返回值本身。

就相当于s就是命名的变量i, 后续所有的操作都是基于
命名变量i(s),返回值也是i, 所以每一次defer操作,
都会更新返回值i。

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值