defer和return

多个defer的执行顺序为“后进先出”

defer、return、返回值的执行逻辑:

  1. return最先执行,return负责将结果写入返回值中;
  2. 接着defer开始执行一些收尾工作;
  3. 最后函数携带当前返回值退出

代码验证

package main
 
import "fmt"
 
func main()  {
    fmt.Println("func1 return: ", func1()) //1000
    fmt.Println("func2 return: ", func2()) //1002
    fmt.Println("func3 return: ", *(func3())) //2
}
 
func func1() int {
    var i int
    defer func() {
        i++
        fmt.Println("func1 defer1: ", i)
    }()
 
    defer func() {
        i++
        fmt.Println("func1 defer2: ", i)
    }()
 
    i = 1000
    return i
}
 
func func2() (i int) {
    defer func() {
        i++
        fmt.Println("func2 defer1: ", i)
    }()
 
    defer func() {
        i++
        fmt.Println("func2 defer2: ", i)
    }()
 
    i = 1000
    return i
}

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

输出如下:

func1 defer2: 1001
func1 defer1: 1002
func1 result: 1000

func2 defer2: 1001
func2 defer1: 1002
func2 result: 1002

func3 defer2: 1
func3 defer1: 2
func3 result: 2

分析

return会将返回值先保存起来,对于无名返回值来说,保存在一个临时对象中,defer是看不到这个临时对象的;而对于有名返回值来说,就保存在已命名的变量中.

func1()int 函数的返回值没有被提前声名,其值来自于其他变量的赋值,而defer中修改的也是其他变量,而非返回值本身,因此函数退出时返回值并没有被改变。

func2()(i int)函数的返回值被提前声名,也就意味着defer中是可以调用到真实返回值的,因此defer在return赋值返回值 i 之后,再一次地修改了 i 的值,最终函数退出后的返回值才会是defer修改过的值。

func3()*int 的返回值没有被提前声明,但是由于 c()*int 的返回值是指针变量,那么在return将变量 i 的地址赋给返回值后,defer再次修改了 i 在内存中的实际值,因此函数退出时返回值虽然依旧是原来的指针地址,但是其指向的内存实际值已经被成功修改了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值