这个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的答案),你可以使用WaitGroupsync包和匿名函数,以避免改变原来的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() }