在Golang中,永不停止的滚动器(Ticker)只工作了两次。

huangapple go评论81阅读模式
英文:

Never ending Ticker in Golang works only 2 times

问题

我正在尝试创建一个具有无限滚动的频道,但它只工作了两次。

你能帮我理解问题出在哪里吗?

代码:

package main 

import (
    "fmt"
    "time"
) 

var mark = [2]float64{8.9876, 762.098568}

func tick(out chan<- [2]float64){

    c := time.NewTicker(time.Millisecond *500)
    for range c.C{
	    out <- mark
    }
}

func main() {

    fmt.Println("Start")

    md := make(chan [2]float64)
    go tick(md)

    for range md{
	    fmt.Println(<-md)
    }
}

输出:

Start
[8.9876 762.098568]
[8.9876 762.098568]

示例:https://play.golang.org/p/P2FaUwbW-3

英文:

I'm trying to make a channel with never ending ticker, but it works only 2 times.

Could you help me to understand where is the problem?

Code:

package main 

import (
&quot;fmt&quot;
&quot;time&quot;
) 

var mark = [2]float64{8.9876, 762.098568}

func tick(out chan &lt;- [2]float64){

    c := time.NewTicker(time.Millisecond *500)
    for range c.C{
	    out &lt;- mark
    }
}

func main() {

    fmt.Println(&quot;Start&quot;)

    md := make(chan [2]float64)
    go tick(md)

    for range &lt;-md{
	    fmt.Println(&lt;-md)
    }
}

Output:

Start
[8.9876 762.098568]
[8.9876 762.098568]

Example: https://play.golang.org/p/P2FaUwbW-3

答案1

得分: 9

这段代码:

for range &lt;-md{

与这段代码:

for range md{

不同。后者遍历通道(你想要的),而前者遍历的是循环开始时从通道接收到的值,这个值恰好是一个包含两个元素的数组,所以会执行两次。你还忽略了for语句中从通道接收到的值,并在循环体中再次从通道中读取值,忽略了通道上的每条其他消息(尽管在这个示例中没有区别,因为每个值都是相同的,但在实际情况下会有很大的区别)。你真正想要的是:

for foo := range md{
    fmt.Println(foo)
}

这是一个经过修改的可以正常工作的playground示例,稍作修改以避免出现“程序运行时间过长”的错误,因为在当前形式下它永远不会停止:https://play.golang.org/p/RSUJFvluU5

英文:

This:

for range &lt;-md{

is not the same as:

for range md{

The latter ranges over the channel (what you want), while the former ranges over the value received from the channel when the loop starts, which happens to be a two-element array, hence the two executions. You're also ignoring the value received from the channel in the for statement, and reading from it again in the loop body, ignoring every other message on the channel (though this makes no difference in the example, since every value is identical, it would make a significant difference in practice). What you really want is:

for foo := range md{
    fmt.Println(foo)
}

Here's a working version of your playground example, slightly modified to avoid "program took too long" errors because in its current form it never stops: https://play.golang.org/p/RSUJFvluU5

huangapple
  • 本文由 发表于 2017年8月18日 01:07:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/45741209.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定