在 Q 群里看到这个问题,小白没想明白
play: https://play.golang.com/p/GB1rSAsoTsz
代码如下:
package main
import (
"fmt"
)
func f2() (x int) {
defer func() {
x++
}()
return 5
}
func main() {
x := f2()
fmt.Println("x: ",x)
}
运行返回: x: 6
1
KaynW 2021-01-07 11:30:04 +08:00 1
匿名返回值和命名返回值 defer 处理的不一样
https://my.oschina.net/henrylee2cn/blog/505535 |
2
Oktfolio 2021-01-07 11:30:29 +08:00 1
return 先执行,5 赋值给 x 了,然后又 x++,最终返回的就是 6,好像是这样?
|
3
catror 2021-01-07 11:31:12 +08:00
因为先执行 return,再执行 defer
|
4
rickiey 2021-01-07 11:34:30 +08:00 1
return 5 在这可以理解分为两步,1 先赋值 x=5,2 再 return 跳转返回 ,而 defer 在 return 之前,也就是 1 和 2 之间,
|
5
rickiey 2021-01-07 11:35:52 +08:00
平时尽量不要给返回值命名,直接返回 int 就行了
|
7
CEBBCAT 2021-01-07 13:19:20 +08:00
|
8
TypeErrorNone 2021-01-07 14:19:03 +08:00
|
9
HiShan 2021-01-07 14:24:58 +08:00
这个变量命名让人迷惑
|
10
RedBlackTree 2021-01-07 14:26:29 +08:00
因为 return 5 包括三步:
1.给栈里的返回值赋值,即 x = 5 ; 2.执行 defer 注册的 func,x++; 3.return 如果是匿名返回值,即没有主动声明变量来指代栈中的返回值,那自然是没办法直接修改的。 因为要使用 defer 修改返回值,所以要使用命名返回值。 |
11
2kCS5c0b0ITXE5k2 2021-01-07 14:37:40 +08:00
golang 为什么那么喜欢写的那么套娃.
|
12
bruce0 2021-01-07 14:49:57 +08:00
这要从 go 的函数调用说起了
C/C++ 等都是用寄存器实现函数返回值的,go 因为支持多返回值, 所以 go 使用调用者的栈空间作为函数的返回值 也就是说 f2 中的 x 实际上是 main 函数中的地址, return5 时,相当于给 x 赋值 5, 在 defer 中 又 x++ 所以 x 就是 6 |
13
frozenshadow 2021-01-07 17:24:48 +08:00 via Android
厚颜无耻的贴一下之前写了一半的分析。能理解楼上各位大佬说的 golang 传值和返回值方式,这个问题就很好理解了 https://timelife.me/index.php/archives/163/
|
14
hbolive 2021-01-08 09:04:33 +08:00
好像某些面试官喜欢问这种问题。。
|