关于 Go defer 对匿名返回值和命名返回值的不同行为

2019-05-14 23:16:26 +08:00
 ArianX
func test1() int {
	var a int

	defer func() {
		a++
	}()

	return a
}

func test2() (a int) {
	defer func() {
		a++
	}()

	return a
}

test1 最终返回 0,test2 最终返回 1

这种令人混淆的行为是一个语言缺陷还是一个 feature ?

今天面试碰上没答起,潜意识认为这两货没区别😥

4034 次点击
所在节点    Go 编程语言
17 条回复
reus
2019-05-14 23:27:58 +08:00
说明你不知道 defer 是在什么时机执行的,基础不牢。
面试就是要试出你的真实水平,有人连 abc 都认不全,难道是字母“令人混淆”?难道是字母有“缺陷”?
ArianX
2019-05-14 23:34:45 +08:00
@reus #1 好的,golang 设计出这两种差异的意愿是因为要说明我基础不牢固
FEDT
2019-05-14 23:40:23 +08:00
有答案吗
zzn
2019-05-14 23:41:29 +08:00
似乎并不怎么令人混淆吧?
blless
2019-05-14 23:42:10 +08:00
你这代码有问题吧
silenceshell
2019-05-14 23:46:59 +08:00
defer 发生在“真正”的 retrun 之前。
Maboroshii
2019-05-14 23:51:01 +08:00
学习了。顺便翻了一下资料
https://blog.golang.org/defer-panic-and-recover
> 3.Deferred functions may read and assign to the returning function's named return values.
ArianX
2019-05-14 23:52:30 +08:00
@silenceshell 这是作用机制层面上的吧。我想讨论的是究竟为什么要这样设计,在什么场景会用到
Zzdex
2019-05-14 23:55:25 +08:00
@ArianX #8 你看楼上的链接,This is convenient for modifying the error return value of a function;
便于修改错误的返回值
victor
2019-05-15 00:02:48 +08:00
ArianX
2019-05-15 00:09:37 +08:00
匿名返回值函数里的 defer 也能访问到返回值,也允许写出修改返回值的语句,为什么要设计为修改对最终返回的值无效?为什么不直接设计为不允许修改?利用到这种差异的场景是什么?
poplar50
2019-05-15 00:14:09 +08:00
学习了,七楼发的链接我看 go tour 的时候还翻过,但是竟然没注意这个。现在想想,defer 既然被设计用来做一些收尾工作,那么出现这种情况就是为了让 defer 也能够处理函数返回值吧。
ArianX
2019-05-15 00:18:28 +08:00
好吧,突然想到某些场景下可能不需要修改最终返回值,但需要在 defer 里使用返回的值做一些操作,于是允许匿名返回值里的 defer 修改返回值,就能够复用同一个变量。
ArianX
2019-05-15 00:22:41 +08:00
话说我想讨论的是为什么要特别设计出匿名返回值和命名返回值 defer 行为的差异,而不是在 defer 里修改返回值的意图
catror
2019-05-15 00:31:33 +08:00
你可以这么理解,返回值其实是关联有一个返回变量的,第一个例子里,因为匿名,defer 函数访问不到返回变量,而变量 a 只是局部变量,修改局部变量自然是影响不到返回变量。
nuance2ex
2019-05-15 00:42:26 +08:00
@ArianX

10 楼,这篇从底层原理说了,刚看了不错。
gamexg
2019-05-15 08:42:21 +08:00
如 @catror 所说可以认为返回值也是一个变量。
test1 里面修改的只是局部变量,并未修改 return 变量。
test2 才是修改的 return 变量。

可以返回结构指针试试,和不同变量一样,test1 修改结构成员也会修改返回值了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/564193

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX