【问题标题】:What does an empty select do?空选择有什么作用?
【发布时间】:2013-09-06 15:44:39
【问题描述】:

我在net/http/httptest 中找到了以下代码,想知道空的select 语句在Go 中的作用。

go s.Config.Serve(s.Listener)
if *serve != "" {
  fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
  select {}
}

【问题讨论】:

    标签: go


    【解决方案1】:

    一个空的select{} 语句永远阻塞。它类似于一个空的for{} 语句。

    在大多数(全部?)支持的 Go 架构上,空选择将产生 CPU。一个空的 for 循环不会,即它会在 100% 的 CPU 上“旋转”。

    【讨论】:

    • 这是我的猜测。但是我仍然觉得它在语义上很尴尬,因为select 建议的是条件而不是循环。
    • AFAIK 一个空的 for 会占用 CPU 资源(至少在其他语言中空的无限循环是这样工作的)。而在 OP 的示例中,很可能 select{} 用于防止主 goroutine 退出。
    • 在 CSP 中,空选择就像STOP,一个永远不会继续的过程。这类似于自死锁,我想它不会经常被使用。但是,该问题为这种模式提出了一个有趣且真实的用例。空的for{} 循环是自活锁,不同的是它消耗cpu 资源。
    • 使用select{}阻塞产生CPU 的主goroutine 似乎是惯用的Go。由于主 goroutine 还没有返回,这就离开了进程,可以分析其他 goroutine 的行为。
    【解决方案2】:

    在 Mac OS X 上,在 Go 中,for { } 将导致 CPU% 达到最大值,并且进程的状态将为 running

    另一方面,select { } 不会导致 CPU% 达到最大值,进程的状态将为sleeping

    【讨论】:

      【解决方案3】:

      空的select 语句只是阻塞了当前的goroutine。

      至于您为什么要这样做,这是一个原因。这个sn-p是等价的

      if *serve != "" {
        fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
        s.Config.Serve(s.Listener)
      } else {
        go s.Config.Serve(s.Listener)
      }
      

      最好不要浪费 goroutine。更糟糕的是,现在有代码重复。作者针对浪费的资源进行了优化,以减少代码重复。但是请注意,永久阻塞 goroutine 检测起来很简单,并且可能比复制版本的成本为零。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-14
        • 1970-01-01
        • 2015-03-11
        • 2018-06-16
        • 2021-10-02
        • 1970-01-01
        • 2017-08-08
        • 1970-01-01
        相关资源
        最近更新 更多