5

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 {}
}

在上面的示例中,返回两个值时k := f2()给出错误,而and - 两个表达式都可以正常工作。为什么会有不同的行为?f2v, ok := m["One"]v := m["One"]

4

1 回答 1

7

从内置的 fetch 中map使用range,在 map、array 或 slice 上使用,并且还type assertions允许一个两个变量。对于用户定义的函数和方法,情况并非如此。如果一个函数声明了两个返回值,你必须告诉如何处理它们,或者忽略它们:

k, _ := f2() // Specify what to do with each returned value
f2() // Ignoring both

为什么?因为规范说是这样的:

地图(索引表达式):

类型为 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
第一个值:key k K
第二个值(如果存在第二个变量):m[k] V

类型断言:

对于接口类型的表达式 x 和 T 类型,主表达式
x.(T)
断言 x 不是 nil 并且存储在 x 中的值是 T 类型。


如果在形式v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)的赋值或初始化中使用类型断言
,则断言的结果是具有类型 (T, bool) 的值对

于 2013-11-02T11:30:47.730 回答