Go 语言入门很简单:Timer

举报
宇宙之一粟 发表于 2022/10/31 19:39:55 2022/10/31
【摘要】 Timer我们经常希望在未来的某个时间点执行 Go 代码,或者在某个时间间隔重复执行。 Go 的内置计时器和自动收录器功能使这两项任务变得简单。Timer 是一个定时器。代表未来的一个单一事件,你可以告诉 timer 你要等待多长时间。Timer 结构体:type Timer struct { C <-chan Time r runtimeTimer}它提供一个 channel,在定...

Timer

我们经常希望在未来的某个时间点执行 Go 代码,或者在某个时间间隔重复执行。 Go 的内置计时器和自动收录器功能使这两项任务变得简单。

Timer 是一个定时器。代表未来的一个单一事件,你可以告诉 timer 你要等待多长时间。

Timer 结构体:

type Timer struct {
   C <-chan Time
   r runtimeTimer
}

它提供一个 channel,在定时时间到达之前,没有数据写入 timer.C 会一直阻塞。直到定时时间到,向 channel 写入值,阻塞解除,可以从中读取数据。

计时器代表未来的单个事件。您告诉计时器您要等待多长时间,它提供了一个届时将通知的通道。此计时器将等待 2 秒。

​<-timer1.C​​  在定时器的通道 C 上阻塞,直到它发送一个指示定时器触发的值

如果您只是想等待,您可以使用 time.Sleep。计时器可能有用的一个原因是您可以在计时器触发之前取消它。这是一个例子。

package main

import (
    "fmt"
    "time"
)

func main() {

    timer1 := time.NewTimer(2 * time.Second)

    <-timer1.C
    fmt.Println("Timer 1 fired")

    timer2 := time.NewTimer(time.Second)
    go func() {
        <-timer2.C
        fmt.Println("Timer 2 fired")
    }()
    stop2 := timer2.Stop()
    if stop2 {
        fmt.Println("Timer 2 stopped")
    }

    time.Sleep(2 * time.Second)
}

给 ​​timer2​​  足够的时间来触发它,如果它会触发的话,以表明它实际上已经停止了。

第一个计时器将在我们启动程序后约 2 秒触发,但第二个应该在它有机会触发之前停止.

运行该代码:

$ go run timers.go
Timer 1 fired
Timer 2 stopped


time.After

​time.After​​  等待指定的持续时间,然后在返回的通道上发送当前时间:

select {
case news := <-AFP:
        fmt.Println(news)
case <-time.After(time.Hour):
        fmt.Println("No news in an hour.")
}

在计时器触发之前,垃圾收集器不会回收底层的 time.Timer。如果这是一个问题,请改用 ​​time.NewTimer​​​  并在不再需要计时器时调用其 ​​Stop​​  方法:

for alive := true; alive; {
        timer := time.NewTimer(time.Hour)
        select {
        case news := <-AFP:
                timer.Stop()
                fmt.Println(news)
        case <-timer.C:
                alive = false
                fmt.Println("No news in an hour. Service aborting.")
        }
}

Timer 模式

package main

import (
    "time"
    "fmt"
)

const time_in_seconds = 60

func main() {
    // 60 second timer.
    timer := time.NewTimer(time.Second*time_in_seconds)
    // Stop the timer at the end of the function. 
    // Defers are called when the parent function exits.
    defer timer.Stop()
    
    // Wait for timer to finish in an asynchronous goroutine
    go func() {
        // Block until timer finishes. When it is done, it sends a message 
        // on the channel timer.C. No other code in 
        // this goroutine is executed until that happens.
        <-timer.C
        // If main() finishes before the 60 second timer, we won't get here
        fmt.Printf("Congratulations! Your %d second timer finished.", time_in_seconds)
    }
    
    executeTheCodeThatMightTakeMoreThanSixtySeconds()
    
    // The main function is finished, so the timer will be told to stop.
}

提取定时器实用功能

我们将上述模式提取为效用函数。它在指定的时间段内运行计时器,然后调用提供的函数。

package main

import (
  "time"
  "fmt"
)

const time_in_seconds = 60

func main() {

  // Run timer for 60 seconds. When timer expires, 
  // call a function to print out that our timer is done.
  timer := NewTimer(time_in_seconds, func() {
    fmt.Printf("Congratulations! Your %d second timer finished.", time_in_seconds)
  })
  defer timer.Stop()
  
  
  executeTheCodeThatMightTakeMoreThanSixtySeconds()
}

// NewTimer creates a timer that runs for a specified number of seconds. 
// When the timer finishes, it calls the action function.
// Use the returned timer to stop the timer early, if needed.
func NewTimer(seconds int, action func()) *time.Timer {
  timer := timer.NewTimer(time.Seconds * time.Duration(seconds))
  
  go func() {
    <-timer.C
    action()
  }
  
  return timer
}

TimeAfterFunc 函数

timer := time.AfterFunc(time.Second*60, func() {
    fmt.Printf("Congratulations! Your %d second timer finished.", time_in_seconds)
})
defer timer.Stop()
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。