为了账号安全,请及时绑定邮箱和手机立即绑定

如何遍历 go time.Tick 通道?

如何遍历 go time.Tick 通道?

Go
慕斯709654 2021-10-18 14:50:29
我在使用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()调用时通道没有关闭。在这种情况下,迭代代码通道的惯用方法是什么?
查看完整描述

2 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

你是对的,股票的通道没有在停止时关闭,这是在文档中说明的:


停止关闭自动收报机。停止后,将不再发送报价单。停止不会关闭通道,以防止从通道读取不正确地成功。


我相信自动收报机更多的是关于火和忘记,即使你想阻止它,你甚至可以永远挂起例行程序(当然取决于你的应用程序)。


如果你真的需要一个有限的股票代码,你可以做一些技巧并提供一个单独的频道(根据 ThunderCat 的回答),但我要做的是提供我自己的股票代码实现。这应该相对容易,并且会为您提供其行为的灵活性,例如在通道上传递什么或决定如何处理丢失的滴答声(即当读者落后时)。


我的例子:


func finiteTicker(n int, d time.Duration) <-chan time.Time {

    ch := make(chan time.Time, 1)

    go func() {

        for i := 0; i < n; i++ {

            time.Sleep(d)

            ch <- time.Now()

        }

        close(ch)

    }()

    return ch

}


func main() {   

    for range finiteTicker(10, 100*time.Millisecond) {

        fmt.Println("hi")

    }

}

http://play.golang.org/p/ZOwJlM8rDm


查看完整回答
反对 回复 2021-10-18
?
杨魅力

TA贡献1811条经验 获得超6个赞

我也在 IRC 上问过,从@Tv` 那里得到了一些有用的见解。


尽管timer.Ticker看起来它应该是 go pipeline 的一部分,但它实际上并不能很好地与管道习语配合使用:


以下是管道建设指南:


当所有发送操作完成后,stage 关闭它们的出站通道。

阶段不断从入站通道接收值,直到这些通道关闭或发送方被解除阻塞。

管道通过确保所有发送的值有足够的缓冲区或在接收方可能放弃通道时明确通知发送方来解除对发送方的阻塞。


这种不一致的原因似乎主要是为了支持以下习语:


for {

    select {

    case <-ticker.C:

        // do something

    case <-done:

        return

    }

}

我不知道为什么会这样,以及为什么没有使用流水线习语:


for {

    select {

    case _, ok := <-ticker.C:

        if ok {

            // do something

        } else {

            return

        }

    }

}

(或更干净)


for _ = range ticker.C {

    // do something

}

但这是要走的路:(


查看完整回答
反对 回复 2021-10-18
  • 2 回答
  • 0 关注
  • 205 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信