Go 命名返回值和非命名返回值在使用 defer 时的不同表现
· 阅读需 2 分钟
使用命名返回值
通过 defer
修改这个返回值。
package main
import "fmt"
func modifyWithNamedReturn() (result int) {
defer func() {
result += 5 // 修改命名返回值
}()
return 10 // 初始设置返回值为 10
}
func main() {
fmt.Println(modifyWithNamedReturn()) // 输出 15
}
解释
- 这个函数
modifyWithNamedReturn
中有一个命名返回值result
。 - 函数返回时,首先设置
result
为10
。 - 在函数实际返回前,
defer
语句执行,将result
的值增加5
。 - 因此,虽然
return
语句最初将返回值设置为10
,defer
修改后,最终返回值变为15
。
使用非命名返回值
defer
如何无法修改返回值。
package main
import "fmt"
func modifyWithoutNamedReturn() int {
var result int
defer func() {
result += 5 // 尝试修改,但不影响返回值
}()
result = 10 // 设置 result 的值
return result // 返回 result 的值
}
func main() {
fmt.Println(modifyWithoutNamedReturn()) // 输出 10
}
解释
- 函数
modifyWithoutNamedReturn
返回一个非命名返回值。 result
被设置为10
,并准备用作返回值。- 尽管
defer
函数将result
增加了5
,但这种修改发生在返回值被确定(已复制)后,因此对实际返回给调用者的值没有影响。 - 最终输出为
10
,展示了即使defer
修改了局部变量result
,也不会改变返回值。
defer 使用总结
defer
在命名返回值情况下可以修改最终的返回值,因为命名返回值的作用域延伸至整个函数,包括 defer
执行的时间。而在非命名返回值的情况下,return
语句实际上是将值复制到返回位置,此后的 defer
修改不再影响已经设置的返回值。
简单点可以这样理解,命名返回值,说明返回值很重要,要都处理完再返回~