Golang支持为多个左侧变量分配多个返回值。 E.g:
func test() (string, string) {
return "1", "1"
}
a, b := test()
或
a, _ := test()
且接收变量和返回值的数量必须匹配:
b = test() //wrong
但是对于某些内置类型,例如[]或< - ,支持可变数量的返回值
key, exist := map[key]
key := map[key]
我可以从这个频道读取价值
c <- myChan
c, exist <- myChan
我们如何解释这种不一致?这是核心运行/语言保留的功能吗?
答案 0 :(得分:11)
golang specification中明确指出了此行为:
在特殊表单
的赋值或初始化中使用的接收表达式
x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
var x, ok T = <-ch
产生一个额外的无类型布尔结果,报告通信是否成功。如果接收的值是通过成功的发送操作传递给通道,则ok的值为true;如果由于通道关闭且为空而产生的零值,则为false。
在特殊形式的赋值或初始化中使用的类型map [K] V的地图a上的索引表达式
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
产生一个额外的无类型布尔值。如果键x存在于映射中,则ok的值为true,否则为false。
元组赋值将多值运算的各个元素分配给变量列表。有两种形式。在第一个中,右手操作数是单个多值表达式,例如函数调用,通道或映射操作或类型断言。左侧的操作数数量必须与值的数量匹配。例如,如果f是一个返回两个值的函数,
x, y = f()
将第一个值分配给x,将第二个值分配给y。在第二种形式中,左边的操作数必须等于右边的表达式数,每个表达式必须是单值的,而右边的第n个表达式则分配给左边的第n个操作数。
因此,您可以看到此行为是由语言设计指定的,而您无法自己实现为Receive operator
和Index expression
指定的行为。
答案 1 :(得分:2)
你混淆了一个函数返回的多个值与所谓的“逗号ok”习语。
使用函数的返回值,您必须处理所有这些值,或者不处理它们。简单。
“逗号确定”更加微妙。如果您指定了第二个值,行为通常会更改。请考虑以下陈述:
v, ok := x.(int)
// vs
v := x.(int)
如果x
是一个包含整数的接口,那么一切都很好,但是,如果x
拥有不同的类型,则第一个语句将起作用(返回0, false
),第二个语句将返回http
会恐慌。
具有“逗号ok”形式的每种类型的语句都是不同的特殊情况,它们与其他类型的多重赋值(例如多个函数返回值)不同。你不能用它们自己的规则来比较它们,每个都是它自己的东西。