【问题标题】:Go channel: consume data from channel although not push anything to channelGo 通道:从通道中消费数据,但不向通道推送任何内容
【发布时间】:2019-06-13 10:15:16
【问题描述】:

例如我有这个代码:

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 可以增加值?

谢谢

【问题讨论】:

    标签: go channel


    【解决方案1】:

    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
    

    The Go Programming Language Specification

    For statements

    对于带有范围子句的语句

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

    Close 对于带有范围子句的 for 语句很有用。

    【讨论】:

    • 明白。那么我们为什么会使用关闭通道模式的原因对吗?
    • 还有一个问题:两种方法有什么区别:一种是使用关闭通道模式(创建关闭通道,在循环外,完成后,我们将消息推送到此关闭通道)。一种是直接在 select/case 块内检查 (case value, ok := &lt;-c1:)
    • 在有用时使用close 频道。请参阅我修改后的答案。
    猜你喜欢
    • 2015-05-20
    • 2013-10-09
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    相关资源
    最近更新 更多