您看到的解释:
在Go
Playground上,GOMAXPROCS是
1(证明)。
这意味着一次执行一个goroutine,并且如果该goroutine没有阻塞,则不会强制调度程序切换到其他goroutine。
您的代码(像每个Go应用程序一样)以执行
main()函数的goroutine(主goroutine)开始。它启动另一个执行该
other()功能的goroutine
,然后从
done通道接收-阻塞。因此,调度程序必须切换到另一个goroutine(执行
other()功能)。
在
other()函数中,当您在
done通道上发送值时,这将使当前(
other())和
maingoroutine可运行。调度选择继续运行
other(),并且因为
GOMAXPROCS=1,
main()没有继续。现在
other()启动另一个执行无限循环的goroutine。调度程序选择执行此goroutine,这将永远花费到阻塞状态,因此
main()不会继续。
然后,Go Playground沙箱的超时就可以解决:
过程花了太长时间
请注意, Go Memory Model
仅保证某些事件先于其他事件发生,而不能保证如何执行2个并发goroutine。这使得输出不确定。
您不要质疑任何不违反Go Memory
Model的执行顺序。如果您希望执行达到代码中的某些点(执行某些语句),则需要显式同步(您需要同步goroutine)。
另请注意,Go
Playground上的输出已缓存,因此如果再次运行该应用程序,则不会再次运行该应用程序,而是会立即显示已缓存的输出。如果您更改了代码中的任何内容(例如,插入空格或注释),然后再次运行它,它将被编译并再次运行。您会注意到响应时间增加了。使用当前版本(Go
1.6),您每次都会看到相同的输出。
在本地运行(在您的计算机上):
在本地运行它时,很有可能
GOMAXPROCS会大于
1默认值,因为它默认为可用的CPU核心数(从Go
1.5开始)。因此,是否有执行无穷循环的goroutine无关紧要,另一个goroutine将同时执行,即
main(),当
main()返回时,程序终止;它不会等待其他非
main例程完成(请参见规范:程序执行)。
另请注意,即使您将设置
GOMAXPROCS为
1,您的应用也很可能会在“很短的时间内”退出,因为调度程序的实现将切换到其他goroutine,而不仅仅是永久执行无限循环(但是,如上所述,这是不确定的)。然后,它将成为
main()goroutine,因此当
main()完成并返回时,您的应用程序终止。
在Go Playground上玩您的应用程序:
如前所述,默认情况下
GOMAXPROCS位于
1Go Playground上。但是,可以将其设置为更高的值,例如:
runtime.GOMAXPROCS(2)
没有显式同步,执行仍然是不确定的,但是您会观察到不同的执行顺序和终止,而不会发生超时:
Hello, playgroundHereHereHere...<Here is printed 996 times, then:>Finished.
在Go Playground上尝试使用此变体。



