代码之家  ›  专栏  ›  技术社区  ›  Trần Kim Dá»±

Go Channel:使用来自通道的数据,但不向通道推送任何内容

  •  2
  • Trần Kim Dá»±  · 技术社区  · 5 年前

    例如,我有以下代码:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
    
        c1 := make(chan interface{})
        close(c1)
        c2 := make(chan interface{})
        close(c2)
    
        var c1Count, c2Count int
        for i := 1000; i >= 0; i-- {
            select {
            case <-c1:
                c1Count++
            case <-c2:
                c2Count++
            }
    
        }
        fmt.Printf("c1Count: %d\nc2Count: %d\n  ", c1Count, c2Count)
    }
    

    运行时,输出为:

    c1Count: 513
    c2Count: 488
    

    我不知道的是:我们创建C1和C2通道时什么都不做。为什么在select/case块中,c1count和c2count可以增加值?

    谢谢

    1 回复  |  直到 5 年前
        1
  •  4
  •   peterSO    5 年前

    The Go Programming Language Specification

    Close

    在调用close之后,以及在任何以前发送的值 接收,接收操作将返回 通道类型,无阻塞。多值接收操作 返回接收到的值,并指示 通道关闭。


    您正在计算零值。

    例如,

    package main
    
    import (
        "fmt"
    )
    
    func main() {
    
        c1 := make(chan interface{})
        close(c1)
        c2 := make(chan interface{})
        close(c2)
    
        var c1Count, c2Count int
        var z1Count, z2Count int
        for i := 1000; i >= 0; i-- {
            select {
            case z1 := <-c1:
                c1Count++
                if z1 == nil {
                    z1Count++
                }
    
            case z2 := <-c2:
                c2Count++
                if z2 == nil {
                    z2Count++
                }
            }
    
        }
        fmt.Printf("c1Count: %d\nc2Count: %d\n", c1Count, c2Count)
        fmt.Printf("z1Count: %d\nz2Count: %d\n", z1Count, z2Count)
    }
    

    游乐场: https://play.golang.org/p/tPRkqXrAFno

    输出:

    c1Count: 511
    c2Count: 490
    z1Count: 511
    z2Count: 490
    

    GO编程语言规范

    For statements

    对于带range子句的语句

    对于通道,产生的迭代值是连续值 在通道关闭之前发送。如果频道是 零,范围表达式永远阻塞。

    CLOSE对于带有RANGE子句的FOR语句很有用。