Go具有非常简洁的多重返回值范例.但看起来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 {}
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,k := f2()给出错误作为f2返回两个值,而v, ok := m["One"]和v := m["One"]- 两个表达式都没有任何错误.为什么这种行为不同?
从内置中获取map,range在地图,数组或切片上使用,还type assertions允许一个或两个变量.用户定义的函数和方法不是这种情况.如果函数声明了两个返回值,则必须告诉它们如何处理它们,或者忽略它们:
k, _ := f2() // Specify what to do with each returned value
f2() // Ignoring both
Run Code Online (Sandbox Code Playgroud)
为什么?因为规范说它是这样的:
类型map [K] V的映射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
第1个值:键k K
第2个值(如果存在第2个变量):m [k] V
对于接口类型和类型T的表达式
x ,主表达式x.(T)
断言x不是nil,并且存储在x中的值是T类型.
和
如果在表单
v 的赋值或初始化中使用了类型断言,则ok = x.(T)
v,ok:= x.(T)
var v,ok = x.(T)
断言的结果是a一对带有类型的值(T,bool)