douyihuaimao733955 2017-12-06 12:18
浏览 103
已采纳

从封闭通道读取for循环中的select语句永远给出零值

Given this code that simulates fetching of some website-stuff for 3 URL's using a fan-in pattern and range over the condensed channel: https://play.golang.org/p/MSkRI7x4vz

for s := range r {
    println(s)
}

This works well, but I want to use an overall timeout signal channel, so I try to use a select in a for-loop like this: https://play.golang.org/p/LjDoIc0j-z

totalTimeout := time.After(300 * time.Millisecond)
loop:
    for {
        select {
        case s := <-r:
            fmt.Println(s)
        case <-totalTimeout: // signaling usage of a channel
            fmt.Println("Timed out")
            break loop
        }
    }
}

This behaves not well: After the input channels are closed, the condensed channel from fan-in is closed. But now zero-values are read until the timeout effectively occurs. When I read http://www.tapirgames.com/blog/golang-channel or the specs https://golang.org/ref/spec#Close it seems that receiving from a closed channel "never blocks" and thus gives back zero values. I can only guess, that a range detects the close, where the select cannot, because it's condition is a read from a channel in itself.

I could break out like this

case s := <-r:
    if s == "" {
        break loop
    }
    fmt.Println(s)

Is there another approach to stop getting empty values or is this the proper idiomatic way using a select in a for loop?

  • 写回答

1条回答 默认 最新

  • douhuang75397 2017-12-06 14:19
    关注

    Receive on a closed channel yields the zero value after all elements in the channel are received.

    Use the two value receive to detect when the channel is closed and break from the loop. The second value is false when the channel yields a zero value because the channel is closed.

    for {
        select {
        case s, ok := <-r:
            if !ok {
                break loop
            }
            fmt.Println(s)
        case <-totalTimeout: // signaling usage of a channel
            fmt.Println("Timed out")
            break loop
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器