猿问

选择单个案例块,添加默认值:unblocks

在用这样的东西测试一些代码时:


// ch := make(chan error)


for {

    select {

      case <- ch:

           println("here")

    }

}

我注意到,如果我不添加default代码块:


for {

    select {

       case <- ch:

            println("here")

       default:

    }

}

如果需要该块,最好使用range,例如:


for {

    for _ = range <- ch {

        println("here")

    }

}

或者在这种情况下使用selectover有什么区别/优势吗?range


红颜莎娜
浏览 482回答 3
3回答

慕姐4208626

1-当您处理一个频道时,可以使用for,考虑这个工作代码(The Go Playground):package mainimport "fmt"func main() {&nbsp; &nbsp; ch := make(chan int, 2)&nbsp; &nbsp; ch <- 1&nbsp; &nbsp; ch <- 2&nbsp; &nbsp; close(ch)&nbsp; &nbsp; for range ch {&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Done.")}这将清空通道。注意:您应该close使用通道或使用break语句来完成该循环。2- 当您处理更多可能使用的频道时select,就像这样(The Go Playground):for {&nbsp; &nbsp; select {&nbsp; &nbsp; case <-pause:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("pause")&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-play:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("play")&nbsp; &nbsp; &nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; work()&nbsp; &nbsp; }}3- 使用 nil 和封闭通道(The Go Playground):package mainimport "fmt"func main() {&nbsp; &nbsp; var quit chan struct{} // nil&nbsp; &nbsp; select {&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("1")&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("2") // This runs&nbsp; &nbsp; }&nbsp; &nbsp; quit = make(chan struct{}, 1)&nbsp; &nbsp; select {&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("10")&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("20") // This runs&nbsp; &nbsp; }&nbsp; &nbsp; quit <- struct{}{} // send&nbsp; &nbsp; select {&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("100") // This runs&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("200")&nbsp; &nbsp; }&nbsp; &nbsp; close(quit)&nbsp; &nbsp; select {&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("1000") // This runs&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("2000")&nbsp; &nbsp; }&nbsp; &nbsp; select {&nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("10000") // This runs&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("20000")&nbsp; &nbsp; }}输出:220100100010000选择语句“选择”语句选择一组可能的发送或接收操作中的哪一个将继续。它看起来类似于“switch”语句,但所有案例都涉及通信操作。具有 RecvStmt 的案例可以将 RecvExpr 的结果分配给一个或两个变量,这些变量可以使用短变量声明来声明。RecvExpr 必须是(可能带括号的)接收操作。最多可以有一个默认案例,它可能出现在案例列表中的任何位置。“select”语句的执行分几个步骤进行:对于语句中的所有情况,在输入“select”语句时,接收操作的通道操作数以及发送语句的通道和右侧表达式仅按源顺序计算一次。结果是一组要接收或发送到的通道,以及要发送的相应值。无论选择哪种(如果有)通信操作进行,该评估中的任何副作用都会发生。RecvStmt 左侧的带有短变量声明或赋值的表达式尚未计算。如果一个或多个通信可以进行,则通过统一的伪随机选择选择一个可以进行的通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,则“选择” 语句块,直到至少有一个通信可以进行。除非所选案例是默认案例,否则执行相应的通信操作。如果所选用例是带有短变量声明或赋值的 RecvStmt,则计算左侧表达式并分配接收到的值(或多个值)。执行所选案例的语句列表。由于 nil 通道上的通信永远无法进行,因此只有 nil 通道且没有默认案例的选择会永远阻塞。执行所选案例的语句列表。由于 nil 通道上的通信永远无法进行,因此只有 nil 通道且没有默认案例的选择会永远阻塞。执行所选案例的语句列表。由于 nil 通道上的通信永远无法进行,因此只有 nil 通道且没有默认案例的选择会永远阻塞。

斯蒂芬大帝

在您的情况下,似乎一个简单的循环就足够了:for&nbsp;_&nbsp;=&nbsp;range&nbsp;ch&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println("drain")}如果您有多个goroutines 需要处理,则 Select 是必需的。巡回赛有一个range 和 close的例子。另一种情况select是幂等通道关闭: https:&nbsp;//play.golang.org/p/_Ol42BvuuS。

慕工程0101907

如果 select 中只有一种情况,那么最好use for range instead of for { select {} } (gosimple)使用S1000golint 检查。for range代码就像:for&nbsp;range&nbsp;ch&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println("here")}
随时随地看视频慕课网APP

相关分类

Go
我要回答