What exactly is happening when Go returns multiple values

huangapple go评论75阅读模式
英文:

What exactly is happening when Go returns multiple values

问题

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

func learnMultiple(x, y int) (sum, prod int) {
    return x + y, x * y // 返回两个值
}

sum, prod := learnMultiple(10, 50)

这与返回一个元组类似吗?

我来自Ruby领域,在那里我可以返回一个数组和一个和积。

sum, prod = ["60", "500"]
英文:

Go functions and methods can return multiple values.

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

sum, prod := learnMultiple(10, 50)

Is it similar to returning a tuple?

I come from ruby land where I can return an array and a

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

答案1

得分: 11

我们可以轻松查看一些编译代码来确认幕后发生了什么。

考虑以下代码片段:

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 语言的编译器所做的类似,只是其规范仅定义了单个返回值。

英文:

We can easily look at some compiled code to confirm what's going on behind the scenes.

Consider this snippet:

func f() (a, b byte) {
    return &#39;x&#39;, &#39;y&#39;
}

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

If we disassemble the created ELF binary, you'll see something like this (inlining was disabled so we could see the call happening):

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

0000000000400c10 &lt;main.main&gt;:
(...)
400c25:       48 83 ec 10             sub    $0x10,%rsp
400c29:       e8 d2 ff ff ff          callq  400c00 &lt;main.f&gt;
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
(...)

So f just puts the result bytes in the stack, and main picks them back and puts them in working registers. A different compiler might also choose to pass these values around between the two scopes straight into registers.

This is all similar to what a compiler for the C language would do, except its specification defines a single return value only.

答案2

得分: 3

这类似于返回一个元组,就像一些语言(如Python)使用元组来实现多个返回值一样。

但是在Go语言中,没有元组这个概念。一个返回一个值的函数会在栈上分配一个槽位来保存它。一个返回两个值的函数会在栈上分配两个槽位来保存它们。依此类推...

英文:

It is similar to returning a tuple, in the sense that some languages (like python) use tuples to implement multiple return values.

But in Go there is no such thing as a tuple. A function that returns one value allocates one slot on the stack to hold it. A function that returns two values allocates two slots on the stack to hold them. And so on…

huangapple
  • 本文由 发表于 2013年9月5日 03:57:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/18622706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定