猿问

Go中没有Goroutine的输出

SayHello()按预期执行,Goroutine将不打印任何内容。

package mainimport "fmt"func SayHello() {
    for i := 0; i < 10 ; i++ {
        fmt.Print(i, " ")
    }}func main() {
    SayHello()
    go SayHello()}


喵喵时光机
浏览 1267回答 3
3回答

尚方宝剑之说

当你main()函数结束,您的程序也结束了。它不会等待其他的峡谷完成。引用Go语言规范:程序执行:程序执行从初始化主包开始,然后调用函数。main..当函数调用返回时,程序将退出。它不会等待其他的(非-main)完成的大猩猩。看见这个答案更多细节。你得告诉你的main()函数等待SayHello()函数开始时是一个要完成的Goroutine。您可以将它们与通道同步,例如:func&nbsp;SayHello(done&nbsp;chan&nbsp;int)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Print(i,&nbsp;"&nbsp;") &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;done&nbsp;!=&nbsp;nil&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;<-&nbsp;0&nbsp;//&nbsp;Signal&nbsp;that&nbsp;we're&nbsp;done &nbsp;&nbsp;&nbsp;&nbsp;}}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;SayHello(nil)&nbsp;//&nbsp;Passing&nbsp;nil:&nbsp;we&nbsp;don't&nbsp;want&nbsp;notification&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;:=&nbsp;make(chan&nbsp;int) &nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;SayHello(done) &nbsp;&nbsp;&nbsp;&nbsp;<-done&nbsp;//&nbsp;Wait&nbsp;until&nbsp;done&nbsp;signal&nbsp;arrives}另一种选择是关闭通道,发出信号表示完成:func&nbsp;SayHello(done&nbsp;chan&nbsp;struct{})&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Print(i,&nbsp;"&nbsp;") &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;done&nbsp;!=&nbsp;nil&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(done)&nbsp;//&nbsp;Signal&nbsp;that&nbsp;we're&nbsp;done &nbsp;&nbsp;&nbsp;&nbsp;}}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;SayHello(nil)&nbsp;//&nbsp;Passing&nbsp;nil:&nbsp;we&nbsp;don't&nbsp;want&nbsp;notification&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;:=&nbsp;make(chan&nbsp;struct{}) &nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;SayHello(done) &nbsp;&nbsp;&nbsp;&nbsp;<-done&nbsp;//&nbsp;A&nbsp;receive&nbsp;from&nbsp;a&nbsp;closed&nbsp;channel&nbsp;returns&nbsp;the&nbsp;zero&nbsp;value&nbsp;immediately}注:根据您的编辑/注释:如果要运行2SayHello()函数随机打印“混合”数字:你不能保证观察这种行为。再次,请参阅上述答复更多细节。这个GO记忆模型只有保证某些事件发生在其他事件之前,才能保证如何执行2个并发的goroutines。您可以尝试它,但知道结果不会是决定性的。首先,您必须允许使用以下方法执行多个活动的goroutines:runtime.GOMAXPROCS(2)第二,你必须先开始SayHello()因为当前代码首先执行SayHello()在主要的Goroutine中,只有当它完成之后,另一个就开始了:runtime.GOMAXPROCS(2)done&nbsp;:=&nbsp;make(chan&nbsp;struct{})go&nbsp;SayHello(done)&nbsp; //&nbsp;FIRST&nbsp;START&nbsp;goroutineSayHello(nil)&nbsp; //&nbsp;And&nbsp;then&nbsp;call&nbsp;SayHello()&nbsp;in&nbsp;the&nbsp;main&nbsp;goroutine<-done&nbsp; //&nbsp;Wait&nbsp;for&nbsp;completion

不负相思意

或者(对icza的回答)你可以用WaitGroup从…sync包和匿名函数以避免更改原始SayHello.package&nbsp;mainimport&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;"fmt" &nbsp;&nbsp;&nbsp;&nbsp;"sync")func&nbsp;SayHello()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Print(i,&nbsp;"&nbsp;") &nbsp;&nbsp;&nbsp;&nbsp;}}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;SayHello() &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;wg&nbsp;sync.WaitGroup &nbsp;&nbsp;&nbsp;&nbsp;wg.Add(1) &nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;func()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defer&nbsp;wg.Done() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SayHello() &nbsp;&nbsp;&nbsp;&nbsp;}() &nbsp;&nbsp;&nbsp;&nbsp;wg.Wait()}为了同时打印数字,在单独的例程中运行每个print语句,如下所示package&nbsp;mainimport&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;"fmt" &nbsp;&nbsp;&nbsp;&nbsp;"math/rand" &nbsp;&nbsp;&nbsp;&nbsp;"sync" &nbsp;&nbsp;&nbsp;&nbsp;"time")func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;wg&nbsp;sync.WaitGroup &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wg.Add(1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;func(fnScopeI&nbsp;int)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defer&nbsp;wg.Done() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;next&nbsp;two&nbsp;strings&nbsp;are&nbsp;here&nbsp;just&nbsp;to&nbsp;show&nbsp;routines&nbsp;work&nbsp;simultaneously &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;amt&nbsp;:=&nbsp;time.Duration(rand.Intn(250)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(time.Millisecond&nbsp;*&nbsp;amt) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Print(fnScopeI,&nbsp;"&nbsp;") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}(i) &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;wg.Wait()}

拉风的咖菲猫

正如其他人所提到的,当main函数返回。一种选择是使用类似于sync.WaitGroup在其他的峡谷里等着main在从main.另一个选择是runtime.Goexit()在……里面main..从戈多:GoExit终止了调用它的Goroutine。没有其他戈鲁丁受到影响。Goexport在终止Goroutine之前运行所有延迟的呼叫。因为GoExit并不是一种恐慌,所以那些延迟函数中的任何恢复调用都会返回零。从主Goroutine调用GoExit将终止该Goroutine,而不需要主返回。由于FuncMain尚未返回,该程序将继续执行其他goroutines。如果其他所有的Goroutines退出,程序就会崩溃。这允许主goroutine在后台例程继续执行时停止执行。例如:package&nbsp;mainimport&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;"fmt" &nbsp;&nbsp;&nbsp;&nbsp;"runtime" &nbsp;&nbsp;&nbsp;&nbsp;"time")func&nbsp;f()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(i) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(10&nbsp;*&nbsp;time.Millisecond) &nbsp;&nbsp;&nbsp;&nbsp;}}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;f() &nbsp;&nbsp;&nbsp;&nbsp;runtime.Goexit()}这可能比永远阻塞主函数更干净,特别是对于无限的程序。一个缺点是,如果进程返回或退出(包括主要的goroutine)的所有循环都会检测到这是一个错误和恐慌:fatal&nbsp;error:&nbsp;no&nbsp;goroutines&nbsp;(main&nbsp;called&nbsp;runtime.Goexit)&nbsp;-&nbsp;deadlock!为了避免这种情况,至少必须有一个Goroutine调用os.Exit在它回来之前。呼叫os.Exit(0)立即终止程序,并表示它没有出错。例如:package&nbsp;mainimport&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;"fmt" &nbsp;&nbsp;&nbsp;&nbsp;"os" &nbsp;&nbsp;&nbsp;&nbsp;"runtime" &nbsp;&nbsp;&nbsp;&nbsp;"time")func&nbsp;f()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(i) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(10&nbsp;*&nbsp;time.Millisecond) &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;os.Exit(0)}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;f() &nbsp;&nbsp;&nbsp;&nbsp;runtime.Goexit()}
随时随地看视频慕课网APP

相关分类

Go
我要回答