带有 select 的 goroute 不会在没有 fmt.Print() 的情况下终止
在 Go Tour 练习 #71 中,带有 select 语句的 goroute除非在默认情况下添加 fmt.Print() 语句,否则将连续执行。出现此行为的原因是存在默认语句时 select 的操作发生了变化。
如果没有默认语句,select 会阻塞,直到在任何正在监视的通道上收到消息为止。通过添加默认值,只要没有通道有消息,select就会执行默认分支。
在原始代码中,default语句创建了一个无限循环:
for { select { case todo := <-toDoList: ... case <-doneCrawling: ... default: if os.Args[1] == "ok" { fmt.Print("") } if crawling == 0 { goto END } } }
没有fmt。默认情况下,调度器无法调度其他goroutine,从而导致死锁。添加 fmt.Print() 可以让调度程序继续其正常功能,从而使 goroutine 能够完成。
修改代码以使用非阻塞 select 可以解决问题:
for { select { case todo := <-toDoList: ... case <-doneCrawling: ... } if crawling == 0 { break } }
或者,可以通过设置 GOMAXPROCS=2 来使原始代码正常工作,这表明调度程序过载存在问题。
以上是为什么 Go 的 select 语句需要 fmt.Print() 来终止特定的 Goroutine?的详细内容。更多信息请关注PHP中文网其他相关文章!