【问题标题】:time.NewTimer doesn't work as I expecttime.NewTimer 不像我预期的那样工作
【发布时间】:2018-11-19 08:13:35
【问题描述】:

我有一个相当简单的程序,它应该在指定的持续时间(例如,一秒)后自行终止

代码:

package main

import (
    "fmt"
    "time"
)

func emit(wordChannel chan string, done chan bool) {
    defer close(wordChannel)

    words := []string{"The", "quick", "brown", "fox"}
    i := 0
    t := time.NewTimer(1 * time.Second)

    for {
        select {
        case wordChannel <- words[i]:
            i++
            if i == len(words) {
                i = 0
            }
        // Please ignore the following case
        case <-done:
            done <- true
            // fmt.Printf("Got done!\n")
            close(done)
            return
        case <-t.C:
            fmt.Printf("\n\nGot done!\n\n")
            return
        }
    }
}

func main() {

    mainWordChannel := make(chan string)
    // Please ignore mainDoneChannel
    mainDoneChannel := make(chan bool)

    go emit(mainWordChannel, mainDoneChannel)

    for word := range mainWordChannel {
        fmt.Printf("%s  ", word)
    }

}

我编译执行二进制,你可以看到执行here

这显然超过 1 秒。

Go 在NewTimer 上的文档是这样写的:

func NewTimer

func NewTimer(d Duration) *Timer

NewTimer 创建一个新的 Timer,它将在至少持续时间 d 之后在其通道上发送当前时间。

有人可以帮我理解这里发生了什么吗?为什么程序在 1 秒后没有完全终止(或接近 at least)?

【问题讨论】:

  • 老实说,在我看来它可能只运行了一秒钟,但我们一直在看着非常慢的终端滚动。注释掉你的打印,看看它运行了多长时间。
  • 在我的机器上测试过了。它工作正常。您主要是在处理缓慢的终端打印。
  • @Thomas 那可能是……

标签: go concurrency channel


【解决方案1】:

计时器按预期工作。它向通道发送一个值。 我认为阅读about select statement很有用 循环中的每次迭代都可以写入通道。 如果 > 1 通信可以继续,则无法保证哪些是。 因此,如果像这样为读取循环添加延迟:

for word := range mainWordChannel {
    fmt.Printf("%s  ", word)
    time.Sleep(time.Millisecond)
}

在这种情况下,只有从timer.C 读取才能继续。程序将结束。

【讨论】:

  • 太棒了。这似乎确实有效。但是,老实说,我仍然不明白为什么它会起作用?你愿意再详细说明一下吗?那真的很有帮助……
  • 这不是一个正确的修复方法。我认为你只是减慢了他的打印速度,以至于终端不会过度缓冲。
  • 我只想重申,睡觉几乎不是答案!虽然您关于 select 的说法是正确的,但在这里睡觉只会让他的程序运行得更慢。他的程序目前没有实际问题。
  • 它不是固定的。它说明了这个问题。选择语句不能保证如果有几个可以继续执行。在您的代码中,值始终可以写入wordChannel。并选择做它。它从不从 timer.C 读取,因为它总是可以写入 wordChannel
猜你喜欢
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 2014-05-16
  • 1970-01-01
  • 2022-01-11
  • 2012-07-13
  • 1970-01-01
相关资源
最近更新 更多