【问题标题】:Default case of select statement keeps executingselect语句的默认情况继续执行
【发布时间】: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还是一直循环?

标签: loops go


【解决方案1】:

如果您在没有超时的情况下执行responder.Recv,您的代码将永远阻塞在那里,您将无法到达default 部分。所以我想尝试设置超时;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    相关资源
    最近更新 更多