介绍
Golang 语言支持命名返回值。
官方建议:
直接返回语句应当仅用在下面这样的短函数中。在长的函数中它们会影响代码的可读性。
而使用普通返回值时,使用
return语句返回时,需要在其后面指定与普通返回值相同类型的参数名。
命名返回值
Go 的返回值可被命名,它们会被视作定义在函数顶部的变量。
返回值的名称应当具有一定的意义,它可以作为文档使用。
没有参数的 return 语句返回已命名的返回值。也就是 直接 返回。
直接返回语句应当仅用在下面这样的短函数中。在长的函数中它们会影响代码的可读性。
而使用普通返回值时,使用 return 语句返回时,需要在其后面指定与普通返回值相同类型的参数名。
package main
import "fmt"
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
普通返回值
普通(匿名)返回值的“好处”是简洁,当我们写一些简短函数或方法时,使用普通返回值可以使代码更加简洁,在 Golang 语言官方标准库中,有很多使用普通返回值的函数或方法。
但是如果返回值是指针类型时,使用普通返回值,就会使我们函数体中的代码变得不优雅,比如以下这段示例代码。
func c() *int {
i := 0
return &i
}
func d() (i *int) {
return
}
当然这里列举的代码片段是个极端示例,我们在编写 Golang 代码时,也并不会这么使用。
踩坑
defer 在命名返回值和普通返回值的函数或方法中,返回的结果不一样。
func main() {
f := fmt.Println
f(a())
f(b())
}
func a() int {
i := 0
defer func() {
i += 1
fmt.Println("a defer:", i)
}()
return i
}
func b() (i int) {
i = 0
defer func() {
i += 1
fmt.Println("b defer:", i)
}()
return i
}
输出结果:
a defer: 1
0
b defer: 1
1
复制
阅读上面这段代码,我们可以发现使用普通返回值的函数 a(),返回结果是 0。使用命名返回值的函数 b(),返回结果是 1。
我们在之前的文章中,也单独介绍过 defer 。在这里我们简述一下,当我们使用 defer 调用一个函数时,该函数的执行,被推迟到周围函数返回的那一刻,要么是因为周围的函数执行了 return 语句,要么是因为相应的 goroutine 崩溃。
在函数 a() 中,因为我们没有使用命名返回值,所以返回结果 return i,其中 i 是一个静态值,即使我们在 defer 调用的函数中给变量 i 执行 +1 操作,返回结果中的变量 i 是不可访问的,所以也不会修改返回结果中的变量 i。
在函数 b() 中,因为我们使用命名返回值,所以变量 i 已被分配,并且被初始化为类型零值。即使 defer 调用的函数在返回结果之后执行,返回结果中的变量 i 仍然是可以被访问的,所以其值仍然可以被修改。
05
总结
在短函数或方法的代码中,可以使用使用命名返回值的直接返回。在长函数中,避免使用直接返回
摘自:
本文探讨了Go语言中命名返回值和普通返回值的使用。官方建议在短函数中使用直接返回,而在长函数中避免使用,以提高代码可读性。命名返回值可以作为文档,且允许在`return`语句后直接返回,但可能影响长函数的可读性。示例展示了两者在`defer`语句中的不同行为,命名返回值的函数在`defer`后仍能修改返回值,而普通返回值则不能。文章提醒开发者在实际编码时要根据情况选择合适的返回方式。

117

被折叠的 条评论
为什么被折叠?



