写法
如果 func
定义,需要指定参数名,应该将返回参数用 ()
包起来
1 2 3 4 5
| func All() (users []User) { database.DB.Find(&users) return users }
|
好处
- 命名返回值在函数开始时会被自动初始化
- 命名返回值可以使函数更加清晰和自说明
- 命名返回值的作用域仅限于函数体内部
注意事项
- 允许在函数内部修改返回值
- 函数有命名返回值,并且在函数体内部存在与命名返回值同名的局部变量,那么局部变量将覆盖命名返回值
- 命名返回值可以在函数体内部进行修改,但如果在函数体内部使用
return
语句显式指定返回值,那么它将覆盖命名返回值的值
示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| package main
import "fmt"
func test() (i int) { i += 1 return }
func main() { fmt.Println("return", test()) }
|
- 在函数体内部使用
return
语句显式指定返回值
1 2 3 4 5 6 7 8 9 10 11 12 13
| package main
import "fmt"
func test() (i int) { x, i := 0, 1 return x }
func main() { fmt.Println("return", test()) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package main
import "fmt"
func test() (i int) { i = 0 defer func() { i += 1 fmt.Println("defer") }() return }
func main() { fmt.Println("return", test()) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package main
import "fmt"
func test() int { i := 0 defer func() { i += 1 fmt.Println("defer") }() return i }
func main() { fmt.Println("return", test()) }
|
通过上面两个例子对比,我们可以看出 i
返回值是不同的,首先我们要知道 defer
的执行时间是在函数返回之前,其次就是命名返回值是可以在函数能部修改的,可以简单理解为 如果函数提内部出现的局部变量和命名返回值的变量名相同,那我们可以认为这个局部变量就是函数返回值的一部分,也就是命名变量 i
,也就是说局部变量 i
是命名返回值变量 i
,所以返回值不一样