如何遍历 go time.Tick 通道?

我在使用time.Tick. 我希望这段代码打印“嗨”10 次,然后在 1 秒后退出,但它挂起:


ticker := time.NewTicker(100 * time.Millisecond)

time.AfterFunc(time.Second, func () {

    ticker.Stop()

})


for _ = range ticker.C {

    go fmt.Println("hi")

}

https://play.golang.org/p/1p6-ViSvma


查看源代码,我看到Stop()调用时通道没有关闭。在这种情况下,迭代代码通道的惯用方法是什么?


慕斯709654
浏览 206回答 2
2回答

婷婷同学_

你是对的,股票的通道没有在停止时关闭,这是在文档中说明的:停止关闭自动收报机。停止后,将不再发送报价单。停止不会关闭通道,以防止从通道读取不正确地成功。我相信自动收报机更多的是关于火和忘记,即使你想阻止它,你甚至可以永远挂起例行程序(当然取决于你的应用程序)。如果你真的需要一个有限的股票代码,你可以做一些技巧并提供一个单独的频道(根据 ThunderCat 的回答),但我要做的是提供我自己的股票代码实现。这应该相对容易,并且会为您提供其行为的灵活性,例如在通道上传递什么或决定如何处理丢失的滴答声(即当读者落后时)。我的例子:func finiteTicker(n int, d time.Duration) <-chan time.Time {&nbsp; &nbsp; ch := make(chan time.Time, 1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < n; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(d)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- time.Now()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; close(ch)&nbsp; &nbsp; }()&nbsp; &nbsp; return ch}func main() {&nbsp; &nbsp;&nbsp; &nbsp; for range finiteTicker(10, 100*time.Millisecond) {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("hi")&nbsp; &nbsp; }}http://play.golang.org/p/ZOwJlM8rDm

杨魅力

我也在 IRC 上问过,从@Tv` 那里得到了一些有用的见解。尽管timer.Ticker看起来它应该是 go pipeline 的一部分,但它实际上并不能很好地与管道习语配合使用:以下是管道建设指南:当所有发送操作完成后,stage 关闭它们的出站通道。阶段不断从入站通道接收值,直到这些通道关闭或发送方被解除阻塞。管道通过确保所有发送的值有足够的缓冲区或在接收方可能放弃通道时明确通知发送方来解除对发送方的阻塞。这种不一致的原因似乎主要是为了支持以下习语:for {&nbsp; &nbsp; select {&nbsp; &nbsp; case <-ticker.C:&nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; case <-done:&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }}我不知道为什么会这样,以及为什么没有使用流水线习语:for {&nbsp; &nbsp; select {&nbsp; &nbsp; case _, ok := <-ticker.C:&nbsp; &nbsp; &nbsp; &nbsp; if ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}(或更干净)for _ = range ticker.C {&nbsp; &nbsp; // do something}但这是要走的路:(
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go