草庐IT

go - 先等待 time.AfterFunc 然后开始 time.NewTicker

coder 2023-07-01 原文

我正在尝试设置一个每小时整点运行的服务例程。在我看来,这两者中的任何一个都很容易。要在整点运行我的例程,我可以使用 time.AfterFunc(),首先计算整点前的剩余时间。为了每小时运行一次例程,我可以使用 time.NewTicker()

但是,我正在努力弄清楚如何仅在传递给 AfterFunc() 的函数触发后才启动 NewTicker

我的 main() 函数看起来像这样:

func main() {
    fmt.Println("starting up")

    // Here I'm setting up all kinds of HTTP listeners and gRPC listeners, none
    // of which is important, save to mention that the app has more happening
    // than just this service routine.

    // Calculate duration until next hour and call time.AfterFunc()
    // For the purposes of this exercise I'm just using 5 seconds so as not to
    // have to wait increments of hours to see the results
    time.AfterFunc(time.Second * 5, func() {
        fmt.Println("AfterFunc")
    })

    // Set up a ticker to run every hour. Again, for the purposes of this
    // exercise I'm ticking every 2 seconds just to see some results
    t := time.NewTicker(time.Second * 2)
    defer t.Stop()
    go func() {
        for now := range t.C {
            fmt.Println("Ticker")
        }
    }()

    // Block until termination signal is received
    osSignals := make(chan os.Signal, 1)
    signal.Notify(osSignals, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
    <-osSignals

    fmt.Println("exiting gracefully")
}

当然 time.AfterFunc() 是阻塞的,我的 Ticker 的有效负载是故意放在一个 go 例程中的,所以它也不会阻塞。这是为了让我的 HTTP 和 gRPC 监听器可以继续监听,但也允许 main() 末尾的代码块在来自操作系统的终止信号时优雅地退出。但现在明显的缺点是 Ticker 几乎立即启动并在传递给 AfterFunc() 的函数触发之前触发两次(2 秒间隔)。输出如下所示:

Ticker
Ticker
AfterFunc
Ticker
Ticker
Ticker
etc.

我想要的当然是:

AfterFunc
Ticker
Ticker
Ticker
Ticker
Ticker
etc.

以下也不起作用,我不确定为什么。它打印 AfterFunc 但 Ticker 从未触发。

time.AfterFunc(time.Second * 5, func() {
        fmt.Println("AfterFunc")

        t := time.NewTicker(time.Second * 2)
        defer t.Stop()
        go func() {
            for now := range t.C {
                fmt.Println("Ticker")
            }
        }()
    })

最佳答案

The Go Programming Language Specification

Program execution

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

time.AfterFunc(time.Second * 5, func() {
    fmt.Println("AfterFunc")
    t := time.NewTicker(time.Second * 2)
    defer t.Stop()
    go func() {
        for now := range t.C {
            fmt.Println("Ticker")
        }
    }()
})

defer t.Stop() 停止自动收报机。

您不是在等待 goroutine 运行。

关于go - 先等待 time.AfterFunc 然后开始 time.NewTicker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57543721/

有关go - 先等待 time.AfterFunc 然后开始 time.NewTicker的更多相关文章

  1. ruby - 按值降序排列散列,然后按升序键入 ruby - 2

    我有这样的哈希trial_hash={"key1"=>1000,"key2"=>34,"key3"=>500,"key4"=>500,"key5"=>500,"key6"=>500}我按值降序排列:my_hash=trial_hash.sort_by{|k,v|v}.reverse我现在是这样理解的:[["key1",1000],["key4",500],["key5",500],["key6",500],["key3",500],["key2",34]]但我希望当值相同时按键的升序排序。我该怎么做?例如:上面的散列将以这种方式排序:[["key1",1000],["key3",500

  2. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  3. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  4. ruby - Time.to_i 是否总是以 UTC 返回自 EPOCH 以来的秒数? - 2

    无论时间在哪个时区表示,时区差异是否总是被忽略?直觉上,对于那些使用UTC+2的人来说,从EPOCH开始经过的秒数应该更高。然而,事实并非如此。 最佳答案 Epoch基于utc时区https://en.wikipedia.org/wiki/Unix_time它与您当前所在的时区无关。 关于ruby-Time.to_i是否总是以UTC返回自EPOCH以来的秒数?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.

  5. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  6. ruby-on-rails - Ruby/Rails 中的夏令时开始和结束日期 - 2

    我正在开发一个Rails应用程序,我需要在其中找到给定特定偏移量或时区的夏令时开始和结束日期。我基本上在我的数据库中保存了从用户浏览器接收到的时区偏移量(“+3”,“-5”),我想在它出现时修改它由于夏令时的变化。我知道Time实例变量有dst?和isdst方法,如果存储在它们中的日期在夏令时与否。>Time.new.isdst=>true但是使用它来查找夏令时的开始和结束日期会占用太多资源,而且我还必须为我拥有的每个时区偏移量执行此操作。我想知道更好的方法。 最佳答案 好的,基于你所说的和@dhouty'sanswer:您希望能够

  7. ruby-on-rails - phusion passenger 和 ruby​​ 1.9.1 已经开始工作了吗? - 2

    我有一台生产机器和一台开发机器,都运行ubuntu8.10并且都运行最新的phusionpassenger。当我在osx上的本地开发机器上使用ruby​​1.9.1时,我想知道外面的人是否已经在使用带有ruby​​1.9.1甚至1.9.2的phusionpassenger?如果是这样,请告诉我们您的设置!此外,有没有办法在apache上使用phusionpassenger同时运行ruby​​1.8.7(ree)和1.9.1?感谢您的指点,我在任何地方都找不到任何提示... 最佳答案 是的,从某些2.2.x版本开始就正式支持它,我不记

  8. ruby - Rails 3 - 我可以将开始日期设置为 date_select 方法吗? - 2

    date_select方法只能设置:start_year,但我想设置开始日期(例如3个月前的日期)(但没有这样的选项)。那么,我可以将开始日期设置为date_select方法吗?或者,要制作这样的选择框,我应该使用select_tag和options_for_select吗?或者,有什么解决办法吗?谢谢, 最佳答案 有可能……例如:start_year–设置年份选择的开始年份。默认为Time.now.year-5参见thisresource. 关于ruby-Rails3-我可以将开始日期

  9. ruby - 根据值然后键对ruby中的哈希进行排序 - 2

    如何在ruby​​中先根据值然后根据键对散列进行排序?例如h={4=>5,2=>5,7=>1}将排序为[[7,1],[2,5],[4,5]]我可以根据值进行排序h.sort{|x,y|x[1]y[1]}但我不知道如何根据值进行排序,然后在值相同时键入 最佳答案 h.sort_by{|k,v|[v,k]}这使用了Array的事实混入Comparable并定义逐元素。注意上面等价于h.sort_by{|el|el.reverse}相当于h.sort_by(&:reverse)这可能会或可能不会更具可读性。如果你知道Hashes一般都是先

  10. ruby - 从特定索引开始迭代数组 - 2

    我想从特定索引开始遍历数组。我该怎么做?myj.eachdo|temp|...end 最佳答案 执行以下操作:your_array[your_index..-1].eachdo|temp|###end 关于ruby-从特定索引开始迭代数组,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/44151758/

随机推荐