defer

func f1() int {
    x := 5
    defer func() {
        x++
    }()
    return x
}

func f2() (x int) {
    defer func() {
        x++
    }()
    return 5
}
func main() {

    fd := f1()
    fmt.Printf("fd: %v\n", fd)
    haha := f2()
    fmt.Printf("haha: %v\n", haha)
}
 
分别看看f1和f2的汇编
f1:

 f1的返回值是匿名的 所以开辟内存的时候x的内存地址是0x10,匿名返回值的变量是0x8,开辟了两个变量内存

 

 

 

 这里就是先赋值,把0x10中的值给了0x8,然后执行到call defer处 进入defer func

 

 

 汇编中的返回值都是放在EAX中的, 但是可以看见AX的值来自0x8(DX),我其实也不想跟的太深入,因为看不到内存和栈的信息,想看看0x8(DX)的值都看不了,

 向上找,可以看到lea 0x10(SP),DX ,把地址给了DX,DX中存放着X的地址,于是上上图中就自增1,改变的是x的值

这个时候x的0x10(sp)=6,匿名变量0x8(sp)还是等于5 

 

 

 最后取出0x8(sp)中的值放入ax中返回

 

f2:

 这里是指定了返回值x,所以就只需要开辟了x的内存,

 保存地址

 

自增1  返回到上层函数 取值 返回

 

 

 

 至于为什么f1和f2在自增的时候都是通过0x8(dx)得到的值,没深入跟,也不好跟,但肯定是在某个地方有处理,当前只能通过DX来判断 地址存入的寄存器,

所以就简单的总结下:

当返回值是匿名变量的时候,会开辟匿名变量的内存,真正返回的时候也是返回的这个匿名变量的值,因为是匿名的所以无法对它修改,

x:=5,return x, defer fun(){x++},x=5,return时赋值给匿名变量,x++后x=6 ,匿名变量还是5,返回的是匿名变量

 

当返回值不是匿名变量的时候,会直接开辟这个变量的内存,返回的时候也是为这个变量赋值,在defer func在函数内改变的也是这个变量,

posted @ 2022-03-05 21:36  咖喱给给啊  阅读(169)  评论(0)    收藏  举报