【Go - 定时器知多少,4种常见场景】
Go 语言中有几种方式可以实现定时执行逻辑,主要通过 time
包提供的 Timer
和 Ticker
来实现。
1 - 延时执行
1.1 使用 time.Timer
实现一次性定时任务
time.Timer
用于在未来某一时刻执行一次任务。以下是一个示例:
package main
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(2 * time.Second) // 创建一个定时器,设置时间为2秒后
currtime := <-timer.C // 阻塞直到定时器的通道 C 发送了定时事件
fmt.Println("Current time:", currtime)
fmt.Println("Timer expired")
}
这里解释下,<-timer.C
在Go语言中,<-timer.C
是一个通道(channel)接收操作,用于从定时器的C
通道接收消息。这里的timer.C
是time.Timer
类型的一个属性,它是一个通道(channel),类型为<-chan Time
。当定时器到期时,当前时间会被发送到C
通道。具体来说,<-timer.C
执行以下操作:
- 阻塞当前goroutine:当前的goroutine会在这一行代码处阻塞,直到
timer.C
通道中有值可以接收。 - 接收通道值:定时器到期后,会向
C
通道发送一个time.Time
类型的值,表示当前时间。这个操作会接收该值,并存到currtime里。 - 继续执行:接收到值后,阻塞解除,程序继续执行下一行代码,即打印"Timer expired"。
简而言之,<-timer.C
在这里用于等待定时器timer
的到期事件。
1.2 使用 time.AfterFunc
实现延迟执行
time.AfterFunc
用于在未来某一时刻执行一次任务,但它允许你指定一个回调函数,当定时器到期时,这个函数将被调用。这对于需要延迟执行某些操作非常有用。
package main
import (
"fmt"
"time"
)
func main() {
time.AfterFunc(2*time.Second, func() {
fmt.Println("Timer expired")
})
// 等待足够的时间以看到定时器到期的消息
time.Sleep(3 * time.Second)
}
2 - 周期执行
2.1 使用 time.Ticker
实现周期性定时任务
time.Ticker
用于周期性执行任务。示例代码,
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(1 * time.Second) // 创建一个定时器,设置周期为1秒
go func() {
for t := range ticker.C {
fmt.Println("Tick at", t)
// process something
}
}()
// 在100秒后停止定时器
time.Sleep(100 * time.Second)
ticker.Stop()
fmt.Println("Ticker stopped")
}
但是注意 上面周期性定时任务,有时并不准时,例如当 定时任务里面有同步的耗时处理,且耗时时间超过时间间隔,则会影响下一次定时任务的启动。
2.2 每次要等上一次执行完,在执行下一次
有些周期性定时任务,是要依次执行,上一次执行完,才可以执行下一次。 执行模型如下,
示例代码
package main
import (
"fmt"
"time"
)
func process() {
// do something.
timer := time.NewTimer(5 * time.Second)
currtime := <-timer.C
fmt.Println("Current time:", currtime)
}
func loopDelayAtleastNSec(n int) {
time.AfterFunc(time.Duration(n)*time.Second, func() {
fmt.Println("Processing ...")
process()
fmt.Println("Process done")
loopDelayAtleastNSec(n)
})
}
func main() {
interval := 2
loopDelayAtleastNSec(interval)
// 创建一个空的通道, 阻塞住
block := make(chan struct{})
<-block
}
结语
这些方法提供了灵活的方式来处理在 Go 程序中的定时任务。选择哪种方式取决于你的具体需求,比如是一次性延时执行、重复执行还是需要延迟调用。
原文地址:https://blog.csdn.net/qq_38428433/article/details/140739082
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!