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在函数内改变的也是这个变量,
浙公网安备 33010602011771号