Go 的函数和方法可以返回多个值:
func GetCard() (Card, error) { ... }
每个返回值都必须按顺序赋值,并用逗号分隔:
card, err := GetCard()
赋值中的每个位置都会声明一个变量。
在 Go 中,不允许声明变量却不使用它。
用空白标识符_代替变量名,就能跳过那个返回值。
card, _ := GetCard() // error intentionally ignored
_, err := GetCard() // card ignored, only checking for error
error是内置接口。
错误值为nil表示没有出错;任何非nil的值都表示出了问题。
按照约定,可能失败的函数应该把error作为最后一个返回值。
调用方必须先检查它,然后才能使用其他返回值:
card, err := GetCard()
if err != nil {
// unsafe to use card here
return err
}
// safe to use card here
这种双值赋值的模式也出现在error处理之外。
map 查找、类型断言和通道接收都会使用第二个布尔值,按约定命名为ok,用来表示成功或数据是否存在:
m := map[string]int{"a": 1}
v, ok := m["a"] // ok is true
v, ok = m["z"] // ok is false
var i interface{} = "hello"
v, ok := i.(string) // ok is true
v, ok = i.(int) // ok is false
v, ok := <-ch // ok is false if ch is closed and empty
返回值也可以在函数签名中命名。 这样,这些变量在函数体内就可以访问了。
func divide(a, b int) (quotient, remainder int) {
quotient = a / b
remainder = a % b
return quotient, remainder
}
命名返回值能说明每个返回位置的含义。
它们还可以配合裸返回使用,也就是不带值的return。
裸返回会隐式返回这些命名变量的当前值:
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
在较长的函数里,裸返回常常会损害可读性,因为很难看出返回的到底是什么。 除非函数足够短、签名始终一目了然,否则优先使用显式返回值。
想了解更多,可以查看 Go by Example:多返回值、Effective Go:多返回值,或者 Go 之旅。