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

map在学习A Tour of Go: Mutating Maps时,我发现令人惊讶的一件事是,我们可以使用单值赋值或双值赋值来访问映射中键的值。示例代码:


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(),根据赋值运算符的左侧返回一个值或两个值吗?


长风秋雁
浏览 117回答 1
1回答

米琪卡哇伊

映射索引操作的一两个值分配是一种特殊形式,为方便起见,不幸的是,它不能在“正常”分配中完成。普通赋值表达式:该规范对元组分配有以下说法:元组赋值将多值运算的各个元素分配给变量列表。有两种形式。首先,右手操作数是单个多值表达式,例如函数调用、通道或映射操作或类型断言。左侧操作数的数量必须与值的数量相匹配。例如,如果 f 是一个返回两个值的函数,x, y = f()将第一个值分配给 x,将第二个值分配给 y。第二种形式,左边的操作数的个数必须等于右边的表达式的个数,每个表达式都必须是单值的,右边的第n个表达式赋值给左边的第n个操作数:one, two, three = '一', '二', '三'这不会为分配中值的数量留下任何歧义的余地。一值或二值表达式:有 4 种情况,表达式左侧同时允许一个值和两个值。其中三个是赋值表达式的特殊形式,最后一个是range子句。索引表达式:索引表达式被定义为 的形式a[x],地图除外:在特殊形式的赋值或初始化中使用的 map [K]V 类型的映射 a 上的索引表达式v, ok = a[x]v, ok := a[x]var v, ok = a[x]产生一个额外的无类型布尔值。接收运营商:接收操作符也会发生同样的情况,通常格式为x <-ch:在特殊形式的赋值或初始化中使用的接收表达式x, ok = <-chx, ok := <-chvar x, ok = <-chvar x, ok T = <-ch产生一个额外的无类型布尔结果,报告通信是否成功。类型断言:再一次提到类型断言中的特殊形式,通常是这样的形式:x.(T)在特殊形式的赋值或初始化中使用的类型断言v, ok = x.(T)v, ok := x.(T)var v, ok = x.(T)var v, ok T1 = x.(T)产生一个额外的无类型布尔值。范围子句:带有 range 子句的for 语句具有与之相关的更宽松的语言,因为它不是对正常赋值表达式的修改:左侧的函数调用在每次迭代时评估一次。对于每次迭代,如果存在相应的迭代变量,则按如下方式生成迭代值:Range expression&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1st value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2nd valuearray or slice&nbsp; a&nbsp; [n]E, *[n]E, or []E&nbsp; &nbsp; index&nbsp; &nbsp; i&nbsp; int&nbsp; &nbsp; a[i]&nbsp; &nbsp; &nbsp; &nbsp;Estring&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s&nbsp; string type&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; index&nbsp; &nbsp; i&nbsp; int&nbsp; &nbsp; see below&nbsp; runemap&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m&nbsp; map[K]V&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key&nbsp; &nbsp; &nbsp; k&nbsp; K&nbsp; &nbsp; &nbsp; m[k]&nbsp; &nbsp; &nbsp; &nbsp;Vchannel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;c&nbsp; chan E, <-chan E&nbsp; &nbsp; &nbsp; &nbsp;element&nbsp; e&nbsp; E非赋值的用途:如上所述,所有三种特殊形式仅用于作业。尝试在其他表达式(函数调用、返回等)中使用多值返回将失败,因为这些不是赋值并且不会从特殊形式中受益。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go