Go 中的哪些语义规则决定何时发生单值赋值与何时发生双值赋值?

What semantic rules in Go decide when a one-value assignment occurs vs. when a two-value assignment occurs?

在从 A Tour of Go: Mutating Maps 研究 map 时,我感到惊讶的一件事是我们可以使用单值赋值或双值赋值来访问映射中键的值。示例代码:

package main

import (
    "fmt"
)

func main() {
    m := map[int]int{2: 4, 3: 9, 4: 16}
    
    // Example 1
    fmt.Println(m[2])
    
    // Example 2
    v := m[2]
    fmt.Println(v)
    
    // Example 3
    v, ok := m[2]
    fmt.Println(v, ok)
}

输出:

4
4
4 true

使用相同语法支持单值赋值和双值赋值涉及哪些语义规则? Go 中是否有其他此类特殊形式支持在相同语法中根据赋值运算符的左侧同时支持单值和双值赋值?

此外,我可以自己编写一个函数 foo() 来 return 根据赋值运算符的左侧可以是单值还是双值吗?

地图索引操作的 one-or-two 值赋值是一种 特殊形式 提供方便,不幸的是不能在“正常”赋值中完成。

普通赋值表达式:

规范对元组有以下说明 assignments:

A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left hand side must match the number of values. For instance, if f is a function returning two values,

x, y = f()

assigns the first value to x and the second to y. In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left:

one, two, three = '一', '二', '三'

这使得赋值中值的数量没有歧义。

一个,或two-value个表达式:

有 4 种情况可以在表达式的左侧同时使用一个值和两个值。其中三个是特殊形式赋值表达式,最后一个是range子句

索引表达式:

Index expressions 被定义为 a[x] 形式,地图除外:

An index expression on a map a of type map[K]V used in an assignment or initialization of the special form

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]

yields an additional untyped boolean value.

接收运算符:

Receive Operator 也是如此,通常是 x <-ch:

A receive expression used in an assignment or initialization of the special form

x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
var x, ok T = <-ch

yields an additional untyped boolean result reporting whether the communication succeeded.

类型断言:

type assertions中再次提到特殊形式,通常形式为x.(T):

A type assertion used in an assignment or initialization of the special form

v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
var v, ok T1 = x.(T)

yields an additional untyped boolean value.

范围子句:

for statement with range clause 具有更宽松的相关语言,因为它不是对正常赋值表达式的修改:

Function calls on the left are evaluated once per iteration. For each iteration, iteration values are produced as follows if the respective iteration variables are present:

Range expression                          1st value          2nd value

array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
string          s  string type            index    i  int    see below  rune
map             m  map[K]V                key      k  K      m[k]       V
channel         c  chan E, <-chan E       element  e  E

用于non-assignments:

如上所述,所有三种 特殊形式 仅用于作业。尝试在其他表达式(函数调用、return 等)中使用 multi-value return 将失败,因为这些不是赋值并且不会从 中受益特殊形式.