dqaxw44567 2018-04-17 07:20
浏览 73
已采纳

从通道读取特定时间的惯用方式

I need to read data from the Go channel for a certain period of time (say 5 seconds). The select statement with timeout doesn't work for me, as I need to read as many values as available and stop exactly after 5 seconds. So far, I've come up with a solution using an extra time channel https://play.golang.org/p/yev9CcvzRIL

package main

import "time"
import "fmt"

func main() {
    // I have no control over dataChan
    dataChan := make(chan string)
    // this is a stub to demonstrate some data coming from dataChan
    go func() {
        for {
            dataChan <- "some data"
            time.Sleep(time.Second)
        }
    }()

    // the following is the code I'm asking about
    timeChan := time.NewTimer(time.Second * 5).C
    for {
        select {
        case d := <-dataChan:
            fmt.Println("Got:", d)
        case <-timeChan:
            fmt.Println("Time's up!")
            return
        }
    }
}

I'm wondering is there any better or more idiomatic way for solving this problem?

  • 写回答

2条回答 默认 最新

  • dongti7838 2018-04-17 07:28
    关注

    That's pretty much it. But if you don't need to stop or reset the timer, simply use time.After() instead of time.NewTimer(). time.After() is "equivalent to NewTimer(d).C".

    afterCh := time.After(5 * time.Second)
    for {
        select {
        case d := <-dataChan:
            fmt.Println("Got:", d)
        case <-afterCh:
            fmt.Println("Time's up!")
            return
        }
    }
    

    Alternatively (to your liking), you may declare the after channel in the for statement like this:

    for afterCh := time.After(5 * time.Second); ; {
        select {
        case d := <-dataChan:
            fmt.Println("Got:", d)
        case <-afterCh:
            fmt.Println("Time's up!")
            return
        }
    }
    

    Also I know this is just an example, but always think how a goroutine you start will properly end, as the goroutine producing data in your case will never terminate.

    Also don't forget that if multiple cases may be executed without blocking, one is chosen randomly. So if dataChan is ready to receive from "non-stop", there is no guarantee that the loop will terminate immediately after the timeout. In practice this is usually not a problem (starting with that even the timeout is not a guarantee, see details at Golang Timers with 0 length), but you should not forget about it in "mission-critial" applications. For details, see related questions:

    force priority of go select statement

    golang: How the select worked when multiple channel involved?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)