What does range or map return?

huangapple go评论102阅读模式
英文:

What does range or map return?

问题

Go语言有一个非常整洁的多返回值范式。但是看起来v, ok := map[key]v, k := range m使用了不同的机制,但使用了相同的符号。下面是一个简单的例子:

func f2() (k, v string) {
    return "Hello", "World"
}

func main(){
    k := f2() // 不工作:在单值上下文中使用了多值f2()

    m := map[string]int{"One": 1}

    // 这个可以工作
    v, ok := m["One"]

    // 这个也可以工作
    v := m["One"]
    for k := range m {}
}

在上面的例子中,k := f2()会报错,因为f2返回了两个值,而v, ok := m["One"]v := m["One"]这两个表达式都可以正常工作,没有任何错误。为什么会有这种不同的行为呢?

英文:

Go has very neat multiple return values paradigm. But It looks like v, ok := map[key] and v, k := range m use different mechanism with same notation. Here is a simple example:

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

In above example, k := f2() gives error as f2 returns two values, whereas v, ok := m["One"] and v := m["One"] - both expressions work without any error.
Why is that different behavior?

答案1

得分: 7

使用内置的map进行提取,使用range在map、数组或切片上进行迭代,以及使用类型断言,可以使用一个或两个变量。但对于用户定义的函数和方法,情况并非如此。如果一个函数声明了两个返回值,你必须告诉编译器如何处理这两个返回值,或者忽略它们:

k, _ := f2() // 指定如何处理每个返回值
f2() // 忽略两个返回值

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

Map(索引表达式):

>对于类型为map[K]V的map a,可以在赋值或初始化的特殊形式中使用索引表达式
>
>v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]

>其中索引表达式的结果是一对具有类型(V, bool)的值。在这种形式中,如果键x存在于map中,则ok的值为true,否则为false。v的值与单返回值形式中的a[x]相同。

Range(for语句):

>对于每次迭代,迭代值的生成方式如下:

>Range表达式: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)的值。

英文:

A fetch from the built in map, using range on a map, array or slice, and also type assertions allows for one or two variables. This is not the case for user defined functions and methods. If a function declares two return values, you must tell what to do with both of them, or ignore both:

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

Why? Because the specification says it is so:

Map (indexed expressions):

>An index expression on a map a of type map[K]V may be used in an assignment or initialization of the special form
>
>v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]

>where the result of the index expression is a pair of values with types (V, bool). In this form, the value of ok is true if the key x is present in the map, and false otherwise. The value of v is the value a[x] as in the single-result form.

Range (for statement):

>For each iteration, iteration values are produced as follows:

>Range expression: m map[K]V
1st value: key k K
2nd value (if 2nd variable is present): m[k] V

Type assertion:

>For an expression x of interface type and a type T, the primary expression
x.(T)
asserts that x is not nil and that the value stored in x is of type T.

and

>If a type assertion is used in an assignment or initialization of the form
v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
the result of the assertion is a pair of values with types (T, bool)

huangapple
  • 本文由 发表于 2013年11月2日 18:56:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/19741174.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定