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 将失败,因为这些不是赋值并且不会从 中受益特殊形式.
在从 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 将失败,因为这些不是赋值并且不会从 中受益特殊形式.