【问题标题】:How to understand the golang multi-return valuegolang多返回值怎么理解
【发布时间】:2017-09-18 04:28:00
【问题描述】:

Golang 支持将多个返回值分配给多个左侧变量。例如:

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

我们如何解释这种不一致?这是核心 go 运行时/语言保留的功能吗?

【问题讨论】:

标签: go return-value


【解决方案1】:

golang specification 中明确规定了这种行为:

  1. Receive operator

在特殊形式的赋值或初始化中使用的接收表达式

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

产生一个额外的无类型布尔结果,报告通信是否成功。如果接收到的值是通过成功的发送操作传递到通道的,则 ok 的值为 true,如果它是由于通道关闭且为空而生成的零值,则为 false。

  1. Index expression

类型为 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。

  1. Assignments

元组赋值将多值运算的各个元素分配给变量列表。有两种形式。首先,右手操作数是单个多值表达式,例如函数调用、通道或映射操作或类型断言。左侧操作数的数量必须与值的数量相匹配。例如,如果 f 是一个返回两个值的函数,

x, y = f()

将第一个值赋给 x,第二个赋给 y。第二种形式,左边的操作数的个数必须等于右边的表达式的个数,每个表达式都必须是单值的,右边的第n个表达式赋值给左边的第n个操作数。

因此,您可以看到此行为是由语言设计指定的,您无法自行实现为 Receive operatorIndex expression 指定的行为。

【讨论】:

    【解决方案2】:

    您将函数返回的多个值与所谓的“comma ok”习语混淆了。

    对于函数的返回值,您必须要么全部处理,要么不处理。很简单。

    “逗号ok”更微妙。如果您指定了第二个值,通常行为会改变。考虑以下陈述:

    v, ok := x.(int)
    // vs
    v := x.(int)
    

    如果x 是一个持有整数的接口,一切都很好,但是,如果x 持有不同的类型,则第一个语句将起作用(返回0, false),而第二个语句将出现恐慌。

    每一种带有“comma ok”形式的语句都是不同的特例,它们与其他种类的多重赋值(如多重函数返回值)不同。你不能比较它们,每个都是它自己的东西,有它自己的规则。

    【讨论】:

      猜你喜欢
      • 2019-05-10
      • 1970-01-01
      • 2011-05-11
      • 2011-09-19
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多