【发布时间】:2014-02-13 14:23:16
【问题描述】:
类似:golang: goroute with select doesn't stop unless I added a fmt.Print()
我正在用 go 编写代码,其中 goroutine 不断接收和处理套接字上的请求。为了停止当前 goroutine 的执行,我将 true 发送到来自其他 goroutine 的通道,当前 goroutine 一直在 select 语句中侦听。
但这里的问题是,即使在通道上发送信号之后,default 块也会永远执行。并且case 块永远不会执行。以下是我遇到问题的代码 sn-p。
for {
select{
//goroutine should return when something is received on channel 's.stopInbox'
case <-s.stopInbox:
fmt.Println("stopInbox")
return
//keep receiving and processing requests until anything is received on channel 's.stopInbox'
default:
fmt.Println("default case")
msg, err := responder.Recv(0)
if err != nil {
fmt.Println("Error receiving message", err.Error())
break
}
envelope := msgToEnvelope(msg)
s.inbox <- &envelope
}
}
我已经搜索了问题并找到了解决方案
使用默认语句 select 将在每次从通道中读取任何内容时运行默认语句。正因为如此,调度程序永远不会有机会调度另一个 goroutine。放入
fmt.Print语句允许调度器调度其他goroutines。
根据建议,我尝试将 print 语句置于默认情况下,我也尝试将 sleep 语句置于默认情况下。但没有任何效果。
有什么办法可以做到这一点吗?也可以通过完全避免select 语句来达到预期的目的吗?
【问题讨论】:
-
你能在操场上发布一个可运行的例子吗?
-
@sk4x0r 我认为您的总体结构没有问题。发到
stopInbox的时候可以发一下相关的部分吗?我还准备了running example of what you want,效果很好。 -
代码是我正在构建的某个库的一部分。我会把代码上传到github上,把链接贴在这里。
-
我在这里上传了代码:github.com/sk4x0r/gocluster@nemo 我还尝试了几个这样的示例,代码按预期工作。但我不知道这里发生了什么。有没有什么办法可以完全避免使用
select语句? -
等等,代码是卡在responder.Recv还是一直循环?