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

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

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 ?

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


更多关于关于 Golang Go语言中 defer 对匿名返回值和命名返回值的不同行为的实战教程也可以访问 https://www.itying.com/category-94-b0.html

18 回复

说明你不知道 defer 是在什么时机执行的,基础不牢。
面试就是要试出你的真实水平,有人连 abc 都认不全,难道是字母“令人混淆”?难道是字母有“缺陷”?

更多关于关于 Golang Go语言中 defer 对匿名返回值和命名返回值的不同行为的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


#1 好的,golang 设计出这两种差异的意愿是因为要说明我基础不牢固

有答案吗

似乎并不怎么令人混淆吧?

你这代码有问题吧

defer 发生在“真正”的 retrun 之前。

学习了。顺便翻了一下资料
https://blog.golang.org/defer-panic-and-recover
> 3.Deferred functions may read and assign to the returning function’s named return values.

这是作用机制层面上的吧。我想讨论的是究竟为什么要这样设计,在什么场景会用到

#8 你看楼上的链接,This is convenient for modifying the error return value of a function;
便于修改错误的返回值

匿名返回值函数里的 defer 也能访问到返回值,也允许写出修改返回值的语句,为什么要设计为修改对最终返回的值无效?为什么不直接设计为不允许修改?利用到这种差异的场景是什么?

学习了,七楼发的链接我看 go tour 的时候还翻过,但是竟然没注意这个。现在想想,defer 既然被设计用来做一些收尾工作,那么出现这种情况就是为了让 defer 也能够处理函数返回值吧。

好吧,突然想到某些场景下可能不需要修改最终返回值,但需要在 defer 里使用返回的值做一些操作,于是允许匿名返回值里的 defer 修改返回值,就能够复用同一个变量。

话说我想讨论的是为什么要特别设计出匿名返回值和命名返回值 defer 行为的差异,而不是在 defer 里修改返回值的意图

你可以这么理解,返回值其实是关联有一个返回变量的,第一个例子里,因为匿名,defer 函数访问不到返回变量,而变量 a 只是局部变量,修改局部变量自然是影响不到返回变量。



10 楼,这篇从底层原理说了,刚看了不错。

如 所说可以认为返回值也是一个变量。
test1 里面修改的只是局部变量,并未修改 return 变量。
test2 才是修改的 return 变量。

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

在Go语言中,defer语句用于延迟函数的执行,直到包含该defer语句的函数即将返回时才执行。defer的行为对于匿名返回值和命名返回值确实有所不同,这主要源于Go语言中返回值的处理方式。

对于匿名返回值,即在函数返回语句中直接返回表达式的结果,Go语言会在函数返回前计算出这些表达式的值,并将这些值存储在临时变量中。defer语句在函数即将结束时执行,此时这些临时变量已经包含了要返回的值。因此,defer语句中修改相关变量不会改变已经计算好的返回值。

而对于命名返回值,Go语言会在函数体中保留这些返回值的命名变量,并在函数返回时直接使用这些变量的值。这意味着,如果在函数体中修改了这些命名返回值,并且在修改后执行了defer语句,defer语句中对这些命名返回值的修改将会影响最终的返回值。

简而言之,defer对匿名返回值的影响较小,因为匿名返回值在返回语句执行前就已经确定了;而对命名返回值的影响较大,因为命名返回值在函数体中保持可修改状态,直到函数真正返回。

因此,在使用defer时,需要特别注意返回值是匿名的还是命名的,以避免因误解defer的行为而导致意外的错误。在实际编程中,建议尽量使用清晰、明确的代码风格,以减少这类问题的发生。

回到顶部