[英]How do chained functions get executed as goroutines?
Given this playground : 鉴于这个游乐场 :
package main
import "fmt"
func main() {
go oneFunc().anotherFunc()
}
func oneFunc() something {
fmt.Println("oneFunc")
return something{}
}
type something struct{}
func (s something) anotherFunc() {
fmt.Println("anotherFunc")
}
Why is the output: 为什么输出:
oneFunc
oneFunc
and "anotherFunc" is never printed? 并且“anotherFunc”从未打印过?
anotherFunc
doesn't execute until oneFunc
returns a value. anotherFunc
不执行,直到oneFunc
返回一个值。 Because of this, the program exits before anotherFunc
is able to run. 因此,程序在
anotherFunc
能够运行之前退出。 You need to wait for anotherFunc
to run before main
exits. 您需要等待
anotherFunc
在main
退出之前运行。
You can do this via Go channels. 您可以通过Go频道完成此操作。 For Example:
例如:
http://play.golang.org/p/dWoLB9afSj http://play.golang.org/p/dWoLB9afSj
package main
import "fmt"
func main() {
ch := make(chan int)
go oneFunc(ch).anotherFunc()
fmt.Println("Waiting...")
<-ch
fmt.Println("Done.")
}
func oneFunc(ch chan int) something {
fmt.Println("oneFunc")
return something{ch}
}
type something struct{
ch chan int
}
func (s something) anotherFunc() {
fmt.Println("anotherFunc")
s.ch <- 1
}
The expression behind the go
keyword is evaluated and the function value of that expression is then executed concurrently. 评估
go
关键字后面的表达式,然后同时执行该表达式的函数值。
So, in your example oneFunc()
is called, hence the oneFunc
output, and the method anotherFunc
on the returned instance is called concurrently. 因此,在您的示例中,
oneFunc()
,因此oneFunc
输出,并且返回实例上的方法anotherFunc
被并发调用。 However, your program terminates before the goroutine can run which is why you don't see anotherFunc
printed. 但是,您的程序会在goroutine运行之前终止,这就是您没有看到打印了
anotherFunc
。
Solution: Use sync.WaitGroup
or channels for synchronization. 解决方案:使用
sync.WaitGroup
或通道进行同步。
To actually (empirically) verify that your go
call executes anotherFunc
concurrently and not oneFunc
you can print the stack in each function and compare the output. 要实际(凭经验)验证您的
go
调用同时执行anotherFunc
而不是 oneFunc
您可以在每个函数中打印堆栈并比较输出。 Example ( on play ): 示例( 正在播放 ):
var wg = sync.WaitGroup{}
func main() {
wg.Add(1)
go oneFunc().anotherFunc()
wg.Wait()
}
func oneFunc() something {
fmt.Println("oneFunc")
buf := make([]byte, 4096)
runtime.Stack(buf, false)
fmt.Println("Stack of oneFunc:", string(buf))
return something{}
}
type something struct{}
func (s something) anotherFunc() {
defer wg.Done()
buf := make([]byte, 4096)
runtime.Stack(buf, false)
fmt.Println("Stack of anotherFunc:", string(buf))
fmt.Println("anotherFunc")
}
You will see something like this: 你会看到这样的事情:
oneFunc
Stack of oneFunc: goroutine 1 [running]:
main.oneFunc()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:20 +0x118
main.main()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x50
Stack of anotherFunc: goroutine 2 [running]:
main.something.anotherFunc()
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:32 +0xb2
created by main.main
/tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x69
anotherFunc
The stack trace even tells you that the two functions are running in different goroutines, no comparison of method calls needed. 堆栈跟踪甚至告诉您这两个函数在不同的goroutine中运行,不需要比较方法调用。
The way that I like to about it is this, go
– like defer
– consumes the last invocation, or pair parentheses, on the line and will invoke that function out of order . 我喜欢它的方式就是这样,
go
-like defer
- 在行上消耗最后一次调用或对括号,并且将不按顺序调用该函数。 Every invocation before that is synchronous. 之前的每次调用都是同步的。
Where go
makes the invocation concurrent. go
使得调用并发。 And defer
delays invocation until current function returns. 并
defer
延迟调用,直到当前函数返回。
There is a really good example of this in the defer
section of Effective Go 在Effective Go的
defer
部分中有一个非常好的例子
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.