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 修改不再影响已经设置的返回值。
简单点可以这样理解,命名返回值,说明返回值很重要,要都处理完再返回~