有返回值的函数,必须有明确的 return 终止语句。
除非有 panic,或者无 break 的死循环,则无须 return 终止语句。
func test(x int) int {
if x > 0 {
return 1
} else if x < 0 {
return -1
}
for {
break
}
} // 错误:missing return at end of function
借鉴自动态语言的多返回值模式,函数得以返回更多状态,尤其是 error 模式。
稍有不便的是没有元组(tuple)类型,也不能用数组、切片接收,但可用 _
忽略掉不想要的返回值。多返回值可用作其他函数调用实参,或当作结果直接返回。
func div(x, y int) (int, error) { // 多返回值列表必须使用括号
if y == 0 {
return 0, errors.New("division by zero")
}
return x / y, nil
}
func log(x int, err error) {
fmt.Println(x, err)
}
func test() (int, error) {
return div(5, 0) // 多返回值用作return结果
}
func main() {
log(test()) // 多返回值用作实参
}
命名返回值
命名返回值让函数声明更加清晰,同时也会改善帮助文档和代码编辑器提示。
命名返回值和参数一样,可当作函数局部变量使用,最后由 return 隐式返回。
func div(x, y int) (z int, err error) {
if y == 0 {
err = errors.New("division by zero")
return
}
z = x / y
return // 相当于:return z, err
}
这些特殊的“局部变量”会被不同层级的同名变量遮蔽。好在编译器能检查到此类状况,只要改为显式 return 返回即可。
func add(x, y int) (z int) {
{
z := x + y // 新定义的同名局部变量,同名遮蔽
return // 错误:z is shadowed during return(改成 "return z" 即可)
}
return
}
除遮蔽外,我们还必须对全部返回值命名,否则编译器会搞不清状况。
func test() (int, s string, e error) {
return 0, "", nil
// 错误:cannot use 0(type int)as type string in return argument
}