这个golang代码有什么问题?
虽然SayHello()
按预期执行,但goroutine不打印任何内容。
package main import "fmt" func SayHello() { for i := 0; i < 10 ; i++ { fmt.Print(i, " ") } } func main() { SayHello() go SayHello() }
当main()
函数结束时,程序也会结束。 它不会等待其他goroutines完成。
引用Go语言规范:程序执行 :
程序执行开始于初始化主包,然后调用
main
函数。 当函数调用返回时,程序退出。 它不会等待其他(非main
)goroutines完成。
看到这个答案的更多细节。
你必须告诉你的main()
函数等待SayHello()
函数作为一个goroutine来完成。 您可以将它们与频道同步,例如:
func SayHello(done chan int) { for i := 0; i < 10; i++ { fmt.Print(i, " ") } if done != nil { done <- 0 // Signal that we're done } } func main() { SayHello(nil) // Passing nil: we don't want notification here done := make(chan int) go SayHello(done) <-done // Wait until done signal arrives }
另一种方法是通过closures通道来表示完成。
func SayHello(done chan struct{}) { for i := 0; i < 10; i++ { fmt.Print(i, " ") } if done != nil { close(done) // Signal that we're done } } func main() { SayHello(nil) // Passing nil: we don't want notification here done := make(chan struct{}) go SayHello(done) <-done // A receive from a closed channel returns the zero value immediately }
笔记:
根据您的编辑/评论:如果您想让2个运行的SayHello()
函数随机打印“混合”数字:您无法保证观察到这种行为。 再次看到上述的答案更多的细节。 Go Memory模型只保证某些事件发生在其他事件之前,你不能保证如何执行两个并发的goroutine。
你可以尝试一下,但是知道结果不是确定性的。 首先,您必须启用多个活动的goroutines才能执行:
runtime.GOMAXPROCS(2)
第二,你必须首先启动SayHello()
作为goroutine,因为当前的代码首先在主goroutine中执行SayHello()
,并且只有在完成后才启动另一个:
runtime.GOMAXPROCS(2) done := make(chan struct{}) go SayHello(done) // FIRST START goroutine SayHello(nil) // And then call SayHello() in the main goroutine <-done // Wait for completion
另外(icza的答案),你可以使用WaitGroup
从sync
包和匿名函数,以避免改变原来的SayHello
。
package main import ( "fmt" "sync" ) func SayHello() { for i := 0; i < 10; i++ { fmt.Print(i, " ") } } func main() { SayHello() var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() SayHello() }() wg.Wait() }
为了同时打印数字,在每个独立的例程中运行每个打印语句,如下所示
package main import ( "fmt" "math/rand" "sync" "time" ) func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func(fnScopeI int) { defer wg.Done() // next two strings are here just to show routines work simultaneously amt := time.Duration(rand.Intn(250)) time.Sleep(time.Millisecond * amt) fmt.Print(fnScopeI, " ") }(i) } wg.Wait() }