简体   繁体   English

空选择有什么作用?

[英]What does an empty select do?

I found the following code in net/http/httptest and wonder what the empty select statement does in Go.我在net/http/httptest找到了以下代码,想知道 Go 中空的select语句做了什么。

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

An empty select{} statement blocks forever.空的select{}语句永远阻塞 It is similar to an empty for{} statement.它类似于空的for{}语句。

On most (all?) supported Go architectures, the empty select will yield CPU.在大多数(全部?)支持的 Go 架构上,空的 select 将产生 CPU。 An empty for-loop won't, ie it will "spin" on 100% CPU.一个空的 for 循环不会,即它会在 100% CPU 上“旋转”。

On Mac OS X, in Go, for { } will cause the CPU% to max, and the process's STATE will be running在 Mac OS X 上,在 Go 中, for { }将导致 CPU% 达到最大值,并且进程的 STATE 将running

select { } , on the other hand, will not cause the CPU% to max, and the process's STATE will be sleeping另一方面, select { }不会导致 CPU% 达到最大值,并且进程的 STATE 将处于sleeping状态

The empty select statement just blocks the current goroutine.空的select语句只会阻塞当前的 goroutine。

As for why you'd do this, here is one reason.至于你为什么要这样做,这是一个原因。 This snippet is equivalent这个片段是等效的

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

It's better in that there isn't a wasted goroutine.更好的是没有浪费的 goroutine。 It's worse in that now there is code repetition.更糟糕的是,现在有代码重复。 The author optimized for less code repetition over a wasted resource.作者针对浪费的资源进行了优化,以减少代码重复。 Note however the permanently block goroutine is trivial to detect and may have zero cost over the duplicating version.但是请注意,永久块 goroutine 检测起来很简单,并且可能比复制版本的成本为零。

Spec#Select_statements : Spec#Select_statements

Since communication on nil channels can never proceed, a select with only nil channels and no default case blocks forever . 由于在零渠道沟通永远不能进行,一个只有零通道和无默认情况下块永远选择。

select {} // block forever

Select statements 选择语句
A "select" statement chooses which of a set of possible send or receive operations will proceed. “选择”语句选择一组可能的发送或接收操作中的哪一个进行。 It looks similar to a "switch" statement but with the cases all referring to communication operations. 它看起来类似于“ switch”语句,但所有情况均涉及通信操作。

A case with a RecvStmt may assign the result of a RecvExpr to one or two variables, which may be declared using a short variable declaration. 具有RecvStmt的案例可以将RecvExpr的结果分配给一个或两个变量,可以使用短变量声明来声明。 The RecvExpr must be a (possibly parenthesized) receive operation. RecvExpr必须是一个(可能带有括号的)接收操作。 There can be at most one default case and it may appear anywhere in the list of cases. 最多可以有一个默认案例,它可能出现在案例列表中的任何位置。

Execution of a "select" statement proceeds in several steps: “ select”语句的执行分几个步骤进行:

  1. For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the "select" statement. 对于该语句中的所有情况,输入“ select”语句后,接收源的通道操作数以及send语句的通道表达式和右侧表达式将按源顺序被精确评估一次。 The result is a set of channels to receive from or send to, and the corresponding values to send. 结果是一组要从中接收或发送到的通道,以及要发送的相应值。 Any side effects in that evaluation will occur irrespective of which (if any) communication operation is selected to proceed. 不管选择进行哪个通信操作,都会发生该评估中的任何副作用。 Expressions on the left-hand side of a RecvStmt with a short variable declaration or assignment are not yet evaluated. 带有简短变量声明或赋值的RecvStmt左侧的表达式尚未评估。

  2. If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. 如果可以进行一种或多种通信,则可以通过统一的伪随机选择来选择可以进行的单个通信。 Otherwise, if there is a default case, that case is chosen. 否则,如果存在默认情况,则选择该情况。 If there is no default case, the "select" statement blocks until at least one of the communications can proceed. 如果没有默认情况,则“ select”语句将阻塞,直到可以进行至少一种通信为止。

  3. Unless the selected case is the default case, the respective communication operation is executed. 除非所选情况是默认情况,否则将执行相应的通信操作。

  4. If the selected case is a RecvStmt with a short variable declaration or an assignment, the left-hand side expressions are evaluated and the received value (or values) are assigned. 如果所选案例是带有简短变量声明或赋值的RecvStmt,则将评估左侧的表达式并分配接收的值(或多个值)。
  5. The statement list of the selected case is executed. 执行所选案例的语句列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM