goroutine 的返回值会发生什么情况?

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

What happens to return value from goroutine

问题

请问有人可以解释一下goroutine返回的值吗?goroutine返回的值是否会被存储?

例如:

// 函数getNumber返回"int i",但我们无法使用这个返回值
// 因为该函数是作为goroutine调用的。
// 我们知道,要在主函数和goroutine之间通信,可以使用通道(chan <- i),
// 但我想知道在goroutine中使用返回值i的用途。是否可以获取/使用这个返回值。
func getNumber(i int) int {
    return i
}

func main() {
    for i := 0; i < 10; i++ {
        go printNumber(i)
    }
    time.Sleep(5)
}

我们应该尽量避免在goroutine中使用返回值吗?

英文:

Could someone please give clarification values returned from the goroutine. Does the returned value from the goroutine is getting stored on stake.

example :

// function getNumber returns the &quot;int i&quot; and we can&#39;t use this returned value
// because this function is invoked as goroutine.
// We know that, to communicate between main and goroutine one could
// use the channel ( chan &lt;- i), but I am interested to know about
// the use of return i in goroutine. Is it possible to get/ use this 
// returned value.
func getNumber(i int) int {
	return i   
	}

func main() {
	
	for i:=0; i&lt;10; i++ {
		go printNumber(i)
		}
	time.Sleep(5)
	}

Should we try to avoid the return valued in go routine ?

答案1

得分: 19

快速查看汇编输出显示:

$ go build -gcflags -S z.go

getNumber() 函数将其结果存储到堆栈中:

"".getNumber t=1 size=16 value=0 args=0x10 locals=0x0
    0x0000 00000 (z.go:5)    TEXT    "".getNumber+0(SB),4,$0-16
    0x0000 00000 (z.go:6)    MOVQ    "".i+8(FP),BX
    0x0005 00005 (z.go:6)    MOVQ    BX,"".~r1+16(FP)
    0x000a 00010 (z.go:6)    RET    ,

因此,当它从 goroutine 中调用时,它会将其结果存储到堆栈中。但是,这是一个新的堆栈,在 goroutine 结束时被销毁,因此无法检索返回值。

"".main t=1 size=96 value=0 args=0x0 locals=0x18
    0x0000 00000 (z.go:9)    TEXT    "".main+0(SB),$24-0
    0x0000 00000 (z.go:9)    MOVQ    (TLS),CX
    0x0009 00009 (z.go:9)    CMPQ    SP,16(CX)
    0x000d 00013 (z.go:9)    JHI    ,22
    0x000f 00015 (z.go:9)    CALL    ,runtime.morestack_noctxt(SB)
    0x0014 00020 (z.go:9)    JMP    ,0
    0x0016 00022 (z.go:9)    SUBQ    $24,SP
    0x001a 00026 (z.go:10)    MOVQ    $0,AX
    0x001c 00028 (z.go:10)    CMPQ    AX,$10
    0x0020 00032 (z.go:10)    JGE    $0,74
    0x0022 00034 (z.go:11)    MOVQ    AX,"".i+16(SP)
    0x0027 00039 (z.go:11)    MOVQ    AX,(SP)
    0x002b 00043 (z.go:11)    MOVQ    $"".getNumber·f+0(SB),CX
    0x0032 00050 (z.go:11)    PUSHQ    CX,
    0x0033 00051 (z.go:11)    PUSHQ    $16,
    0x0035 00053 (z.go:11)    PCDATA    $0,$0
    0x0035 00053 (z.go:11)    CALL    ,runtime.newproc(SB)
    0x003a 00058 (z.go:11)    POPQ    ,CX
    0x003b 00059 (z.go:11)    POPQ    ,CX
    0x003c 00060 (z.go:10)    MOVQ    "".i+16(SP),AX
    0x0041 00065 (z.go:10)    INCQ    ,AX
    0x0044 00068 (z.go:10)    NOP    ,
    0x0044 00068 (z.go:10)    CMPQ    AX,$10
    0x0048 00072 (z.go:10)    JLT    $0,34
    0x004a 00074 (z.go:13)    MOVQ    $5,(SP)
    0x0052 00082 (z.go:13)    PCDATA    $0,$0
    0x0052 00082 (z.go:13)    CALL    ,time.Sleep(SB)
    0x0057 00087 (z.go:14)    ADDQ    $24,SP
    0x005b 00091 (z.go:14)    RET    ,

然而,无法检索这些结果。

英文:

A quick bit of looking at the assembly output shows

$ go build -gcflags -S z.go

The getNumber() function does store its results to the stack

&quot;&quot;.getNumber t=1 size=16 value=0 args=0x10 locals=0x0
	0x0000 00000 (z.go:5)	TEXT	&quot;&quot;.getNumber+0(SB),4,$0-16
	0x0000 00000 (z.go:6)	MOVQ	&quot;&quot;.i+8(FP),BX
	0x0005 00005 (z.go:6)	MOVQ	BX,&quot;&quot;.~r1+16(FP)
	0x000a 00010 (z.go:6)	RET	,

So when it is called from a goroutine, it does store its results to the stack. However this is a new stack which is destroyed when the goroutine ends so there is no possibility of retrieving the return value.

&quot;&quot;.main t=1 size=96 value=0 args=0x0 locals=0x18
	0x0000 00000 (z.go:9)	TEXT	&quot;&quot;.main+0(SB),$24-0
	0x0000 00000 (z.go:9)	MOVQ	(TLS),CX
	0x0009 00009 (z.go:9)	CMPQ	SP,16(CX)
	0x000d 00013 (z.go:9)	JHI	,22
	0x000f 00015 (z.go:9)	CALL	,runtime.morestack_noctxt(SB)
	0x0014 00020 (z.go:9)	JMP	,0
	0x0016 00022 (z.go:9)	SUBQ	$24,SP
	0x001a 00026 (z.go:10)	MOVQ	$0,AX
	0x001c 00028 (z.go:10)	CMPQ	AX,$10
	0x0020 00032 (z.go:10)	JGE	$0,74
	0x0022 00034 (z.go:11)	MOVQ	AX,&quot;&quot;.i+16(SP)
	0x0027 00039 (z.go:11)	MOVQ	AX,(SP)
	0x002b 00043 (z.go:11)	MOVQ	$&quot;&quot;.getNumber&#183;f+0(SB),CX
	0x0032 00050 (z.go:11)	PUSHQ	CX,
	0x0033 00051 (z.go:11)	PUSHQ	$16,
	0x0035 00053 (z.go:11)	PCDATA	$0,$0
	0x0035 00053 (z.go:11)	CALL	,runtime.newproc(SB)
	0x003a 00058 (z.go:11)	POPQ	,CX
	0x003b 00059 (z.go:11)	POPQ	,CX
	0x003c 00060 (z.go:10)	MOVQ	&quot;&quot;.i+16(SP),AX
	0x0041 00065 (z.go:10)	INCQ	,AX
	0x0044 00068 (z.go:10)	NOP	,
	0x0044 00068 (z.go:10)	CMPQ	AX,$10
	0x0048 00072 (z.go:10)	JLT	$0,34
	0x004a 00074 (z.go:13)	MOVQ	$5,(SP)
	0x0052 00082 (z.go:13)	PCDATA	$0,$0
	0x0052 00082 (z.go:13)	CALL	,time.Sleep(SB)
	0x0057 00087 (z.go:14)	ADDQ	$24,SP
	0x005b 00091 (z.go:14)	RET	,

However there is no way of retrieving these results.

答案2

得分: 14

引用自Go语言规范:Go语句

如果函数有任何返回值,在函数完成时它们将被丢弃。

因此,允许将具有返回值的函数作为goroutine执行-这没有任何问题,并且规范明确说明它们的返回值将被简单地丢弃,这不会引发任何错误,但你将无法以通常的方式获取它(就像直接调用函数一样)。

英文:

Quoting from the Go Language specification: Go statements:

> If the function has any return values, they are discarded when the function completes.

So it is allowed to execute functions with return values as goroutines - there is nothing wrong with it, and the specification clearly states that their return values are simply discarded, it will not cause any error but you won't get it in the usually way (as you would by directly calling the function).

答案3

得分: 0

值被丢弃了。go语句没有什么特殊之处。你也可以这样写:

...
_ = getNumber(i)
...

或者只写

...
getNumber(i)
...

甚至

英文:

Values are discarded. And there is nothing special to go statement. You can also write

...
_ = getNumber(i)
...

or just

...
getNumber(i)
...

even

答案4

得分: 0

与大多数其他编程语言不同,Go语言的协程(Go routine)不使用堆栈来存储结果和返回地址。它有一个特殊的内存分配机制,在执行完成后自动销毁。你可以在Go语言的创始人Rob Pike的演讲中了解更多细节。点击这个链接观看YouTube视频:https://www.youtube.com/watch?v=f6kdp27TYZs&index=4&list=LLRA7nvHOCb4nuU7byESOYIg

英文:

Unlike most of the other programming languages, Go routine does not use stack for storing result and return address. It has a special memory allocation for that which destroys itself after execution is completed. you can see details about it in Rob Pike's(founder of golang)talk. visit this link for the youtube video: https://www.youtube.com/watch?v=f6kdp27TYZs&amp;index=4&amp;list=LLRA7nvHOCb4nuU7byESOYIg

答案5

得分: 0

如果你尝试将函数结果分配给变量,像这样:

res := go printNumber(i)

你会得到语法错误,错误信息如下:

prog.go:4:7: 语法错误: 意外的 go,期望表达式

你可以在这里查看。

英文:

FYI: if you try to assign function result to var, like this:

res := go printNumber(i)

you'll get syntax error like this:

prog.go:4:7: syntax error: unexpected go, expecting expression

you can check it out here.

huangapple
  • 本文由 发表于 2015年1月10日 04:06:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/27868369.html
匿名

发表评论

匿名网友

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

确定