选择语句的默认情况会继续执行。

huangapple go评论85阅读模式
英文:

Default case of select statement keeps executing

问题

相似问题:https://stackoverflow.com/questions/12615955/golang-goroute-with-select-doesnt-stop-unless-i-added-a-fmt-print

我正在使用Go编写一段代码,其中一个goroutine在套接字上接收和处理请求。为了停止当前goroutine的执行,我从其他goroutine向一个通道发送true,而当前goroutine在select语句中一直监听该通道。

但问题在于,即使在通道上发送了信号,default块仍然会无限执行。而case块永远不会执行。以下是我遇到问题的代码片段:

for {
    select {
        // 当在通道's.stopInbox'上接收到内容时,goroutine应该返回
        case <-s.stopInbox:
            fmt.Println("stopInbox")
            return

        // 在通道'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
        }
    }
}

我已经搜索了这个问题,并找到了一些解决方案:

使用default语句,select将在没有从通道中读取内容时每次都运行default语句。因此,调度器将永远没有机会调度另一个goroutine。将fmt.Print语句放在其中可以让调度器调度其他goroutine。

根据建议,我尝试在default块中添加了一个打印语句,还尝试在default块中添加了一个休眠语句。但是都没有起作用。

有没有办法使这个工作?还有没有完全避免使用select语句来实现预期效果的方法?

英文:

Similar: https://stackoverflow.com/questions/12615955/golang-goroute-with-select-doesnt-stop-unless-i-added-a-fmt-print

I am writing a code in go, where a goroutine keeps receiving and processing requests on a socket. To stop the execution of current goroutine, I send true to a channel from some other goroutine, for which the current goroutine keeps listening in select statement.

But the problem here is that even after sending signal on channel, default block keeps executing forever. And case block is never executed. Following is the code snippet I am having problem with.

for {
		select{
			//goroutine should return when something is received on channel &#39;s.stopInbox&#39;
			case &lt;-s.stopInbox:
				fmt.Println(&quot;stopInbox&quot;)
				return
			
			//keep receiving and processing requests until anything is received on channel &#39;s.stopInbox&#39;
			default:
				fmt.Println(&quot;default case&quot;)
				msg, err := responder.Recv(0)
				if err != nil {
					fmt.Println(&quot;Error receiving message&quot;, err.Error())
					break
				}
				envelope := msgToEnvelope(msg)
				s.inbox &lt;- &amp;envelope
			}
		}

I have searched for the problem and found solutions as

> With a default statement select will run the default statement every time there is nothing to read from the channels. And because of this, scheduler will never get a chance to schedule another goroutine. Putting the fmt.Print statement in is allowing the scheduler to schedule other goroutines.

As per suggestion, I tried putting a print statement in default case, also I tried putting a sleep statement in default case. But nothing is working.

Is there any way to make this work? Also is it possible to achieve the intended by completely avoiding select statement?

答案1

得分: 3

如果你在没有设置超时的情况下使用responder.Recv,你的代码将永远阻塞在那里,而且你将无法进入default部分。所以我猜你可以尝试设置一个超时时间 选择语句的默认情况会继续执行。

英文:

If you do responder.Recv without a timeout, your code will block there forever and you won't get to the default part. So I guess try setting a timeout 选择语句的默认情况会继续执行。

huangapple
  • 本文由 发表于 2014年2月13日 22:23:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/21756877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定