Go 在无限循环中显示奇怪的行为

Go 在无限循环中显示奇怪的行为,go,channel,Go,Channel,我的Go代码中有非常奇怪的行为。总的要点是当我 for { if messagesRecieved == l { break } select { case result := <-results: newWords[result.index] = result.word messagesRecieved += 1 default: // fmt.Printf("messagesRecieved: %v\n", messagesRecie

我的Go代码中有非常奇怪的行为。总的要点是当我

for {
  if messagesRecieved == l {
    break
  }
  select {
  case result := <-results:
    newWords[result.index] = result.word
    messagesRecieved += 1
  default:
    // fmt.Printf("messagesRecieved: %v\n", messagesRecieved)
    if i != l {
      request := Request{word: words[i], index: i, thesaurus_word: results}
      requests <- request
      i += 1
    }
  }
}
用于{
如果MessagesReceived==l{
打破
}
挑选{
案例结果:=进入版本1.1.2(当前版本)仍然只有原始版本(自初始版本起)goroutine的协作调度。编译器通过插入调度点来改进行为。从内存模型推断,它们位于通道操作旁边。此外,在一些众所周知但故意未记录的位置,例如I/O发生的位置。最后一个解释了为什么取消注释
fmt.Printf
会更改还有,顺便说一句,Go-tip版本现在有一个抢占式调度程序

您的代码使您的一个goroutine在默认的select情况下保持忙碌。由于没有其他不打印的调度点,因此没有其他goroutine有机会取得进展(假设默认的GOMAXPROCS=1)


我建议以避免旋转(忙等待)的方式重写程序的逻辑。一种可能的方法是在默认情况下使用通道发送。作为使用缓冲通道的一个可能很好的副作用,您可以免费从中获得一个简单的限制器。

谢谢!抱歉,这可能不知道,但“提示”是什么版本?还有,你从哪里学到了这么多关于编译器的知识?最好知道从哪里可以获得关于Go在较低级别上发生了什么的信息。谢谢!@elju:这是Go的最新版本/不稳定/开发/尚未完成。如果你是从源代码处编译Go,你可以通过
hg pull&&hg update default获得它&&./all.bash
位于
go/src
目录中。另请参见tip.golang.org,其中提供了该版本的GODOC,即包括使其成为下一计划版本的任何更改。当然,不建议生产tip版本。