选择单个案例块,添加默认值:取消阻止

nba*_*ari 5 go

在使用以下内容测试某些代码时:

// ch := make(chan error)

for {
    select {
      case <- ch:
           println("here")
    }
}
Run Code Online (Sandbox Code Playgroud)

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

for {
    select {
       case <- ch:
            println("here")
       default:
    }
}
Run Code Online (Sandbox Code Playgroud)

如果块是必需的,那么就可以使用range,例如:

for {
    for _ = range <- ch {
        println("here")
    }
}
Run Code Online (Sandbox Code Playgroud)

或者selectrange这种情况下使用结束有什么不同/优势?

小智 7

1-当您处理一个频道时,可以使用for,
考虑这个工作代码(The Go Playground):

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    close(ch)
    for range ch {
    }
    fmt.Println("Done.")
}
Run Code Online (Sandbox Code Playgroud)

这将清空频道.
注意:您应该close使用频道,或者您应该使用breakstatement来完成该循环.


2-当您处理更多可能使用的频道时select,如此(The Go Playground):

for {
    select {
    case <-pause:
        fmt.Println("pause")
        select {
        case <-play:
            fmt.Println("play")
        case <-quit:
            wg.Done()
            return
        }
    case <-quit:
        wg.Done()
        return
    default:
        work()
    }
}
Run Code Online (Sandbox Code Playgroud)

3-使用零和封闭的通道(The Go Playground):

package main

import "fmt"

func main() {
    var quit chan struct{} // nil

    select {
    case <-quit:
        fmt.Println("1")
    default:
        fmt.Println("2") // This runs
    }

    quit = make(chan struct{}, 1)

    select {
    case <-quit:
        fmt.Println("10")
    default:
        fmt.Println("20") // This runs
    }

    quit <- struct{}{} // send

    select {
    case <-quit:
        fmt.Println("100") // This runs
    default:
        fmt.Println("200")
    }

    close(quit)

    select {
    case <-quit:
        fmt.Println("1000") // This runs
    default:
        fmt.Println("2000")
    }

    select {
    case <-quit:
        fmt.Println("10000") // This runs
    default:
        fmt.Println("20000")
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

2
20
100
1000
10000
Run Code Online (Sandbox Code Playgroud)

选择陈述

"select"语句选择一组可能的发送或接收操作中的哪一个将继续.它看起来类似于"switch"语句,但所有情况都涉及通信操作.

具有RecvStmt的情况可以将RecvExpr的结果分配给一个或两个变量,这些变量可以使用短变量声明来声明.RecvExpr必须是(可能是带括号的)接收操作.最多只能有一个默认情况,它可能出现在案例列表中的任何位置.

执行"select"语句分几步进行:

对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入"select"语句后按源顺序精确计算一次.结果是一组要接收或发送的通道,以及要发送的相应值.无论选择哪种(如果有的话)通信操作进行,评估中的任何副作用都将发生.尚未评估具有短变量声明或赋值的RecvStmt左侧的表达式.如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信.否则,如果存在默认情况,则选择该情况.如果没有默认情况,则"select"语句将阻塞,直到至少一个通信可以继续.除非所选择的情况是默认情况,否则执行相应的通信操作.如果所选案例是具有短变量声明或赋值的RecvStmt,则评估左侧表达式并分配接收值(或多个值).执行所选案例的语句列表.由于nil通道上的通信永远不会进行,因此只选择nil通道并且永远不会出现默认情况.


mik*_*iku 5

在你的情况下,似乎一个简单的循环就足够了:

for _ = range ch {
    fmt.Println("drain")
}
Run Code Online (Sandbox Code Playgroud)

如果您有多个goroutine 需要处理,则需要选择。该游览有range 和 close的示例。

另一种情况select是幂等通道关闭:https://play.golang.org/p/_Ol42BvuuS

  • 单例选择的一种用途是幂等通道关闭:https://play.golang.org/p/_Ol42BvuuS (3认同)