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条)

报告相同问题?

悬赏问题

  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输