【问题标题】:What exactly is happening when Go returns multiple values当 Go 返回多个值时到底发生了什么
【发布时间】:2013-09-05 05:21:01
【问题描述】:

Go 函数和方法可以返回多个值。

func learnMultiple(x, y int) (sum, prod int) {
    return x + y, x * y // return two values
}

sum, prod := learnMultiple(10, 50)

和返回元组类似吗?

我来自红宝石之地,在那里我可以返回一个数组和一个

sum, prod = ["60","500"]

【问题讨论】:

  • 不,它只是返回两个值,而不是一个元组。为什么你发现正常返回 1 个值而不是 2 个值?
  • 我只是好奇。我没有发现 1 返回正常。我只是想更好地理解 go 如何返回。

标签: go


【解决方案1】:

我们可以轻松查看一些编译后的代码来确认幕后发生的事情。

考虑一下这个sn-p:

func f() (a, b byte) {
    return 'x', 'y'
}

func main() {
    a, b := f()
    println(a, b)
}

如果我们反汇编创建的 ELF 二进制文件,你会看到类似这样的内容(内联被禁用,因此我们可以看到调用发生):

0000000000400c00 <main.f>:
400c00:       c6 44 24 08 78          movb   $0x78,0x8(%rsp)
400c05:       c6 44 24 09 79          movb   $0x79,0x9(%rsp)
400c0a:       c3                      retq

0000000000400c10 <main.main>:
(...)
400c25:       48 83 ec 10             sub    $0x10,%rsp
400c29:       e8 d2 ff ff ff          callq  400c00 <main.f>
400c2e:       48 0f b6 1c 24          movzbq (%rsp),%rbx
400c33:       48 89 d8                mov    %rbx,%rax
400c36:       48 0f b6 5c 24 01       movzbq 0x1(%rsp),%rbx
(...)

所以f 只是将结果字节放入堆栈,main 将它们取回并放入工作寄存器中。不同的编译器也可能选择将这些值在两个作用域之间直接传递到寄存器中。

这与 C 语言的编译器所做的类似,只是它的规范只定义了一个返回值。

【讨论】:

    【解决方案2】:

    它类似于返回一个元组,从某种意义上说,某些语言(如 python)使用元组来实现多个返回值。

    但是在 Go 中没有元组这样的东西。返回一个值的函数会在堆栈上分配一个槽来保存它。返回两个值的函数会在堆栈上分配两个槽来保存它们。等等……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 2011-01-21
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      相关资源
      最近更新 更多