Go具有非常整洁的多个返回值范例。但是它看起来v, ok := map[key]和v, k := range m使用具有相同符号的不同机制。这是一个简单的示例:
v, ok := map[key]
v, k := range m
func f2() (k, v string) { return "Hello", "World" } func main(){ k := f2() // Doesn't work : multiple-value f2() in single-value context m := map[string]int{"One": 1} // It works v, ok := m["One"] // How it all work? v := m["One"] for k := range m {} }
在上面的示例中,k := f2()给出错误为f2返回两个值,而v, ok := m["One"]和v := m["One"]-两个表达式都正常工作而没有任何错误。为什么会有不同的行为?
k := f2()
f2
v, ok := m["One"]
v := m["One"]
在地图,数组或切片上map使用内建的获取range,并且还type assertions允许一个 或 两个变量。用户定义的函数和方法不是这种情况。如果一个函数声明了两个返回值,则必须告诉他们如何处理这两个返回值,或者忽略这两个值:
map
range
type assertions
k, _ := f2() // Specify what to do with each returned value f2() // Ignoring both
为什么?因为规范说是这样的:
映射(索引表达式):
map [K] V类型的map a上的索引表达式可用于特殊形式的分配或初始化 v,ok = a [x] v,ok:= a [x] var v,ok = a [x] 其中索引表达式的结果是一对类型为(V,bool)的值。以这种形式,如果键x存在于映射中,则ok的值为true,否则为false。v的值是单结果形式的a [x]值。
map [K] V类型的map a上的索引表达式可用于特殊形式的分配或初始化
v,ok = a [x] v,ok:= a [x] var v,ok = a [x]
其中索引表达式的结果是一对类型为(V,bool)的值。以这种形式,如果键x存在于映射中,则ok的值为true,否则为false。v的值是单结果形式的a [x]值。
范围(用于声明):
对于每次迭代,迭代值生成如下: 范围表达式:m map [K] V 第一个值:键k K 第二个值(如果存在第二个变量):m [k] V
对于每次迭代,迭代值生成如下:
范围表达式:m map [K] V 第一个值:键k K 第二个值(如果存在第二个变量):m [k] V
类型断言:
对于接口类型和类型T的表达式 x ,主表达式x。(T) 断言x不是nil,并且存储在x中的值是T类型。
和
如果在类型 v 的赋值或初始化中使用类型声明,则ok = x。(T) v,ok:= x。(T) var v,ok = x。(T) ,声明的结果为一对类型(T,布尔值)的值