有时我们想在自己的服务里单独弄一个定时器,但是又不想让定时器的定时任务成为主线程,而是作为 http 服务或者 rpc 服务的一个子线程来执行任务。
package main
import (
"time"
"fmt"
)
func printDemo() {
fmt.println("demo........")
}
// 初始化 demo 定时器
func InitDemoScheduler() {
// 每 5 秒钟时执行一次
ticker := time.NewTicker(5 * time.Second) // 创建一个定时器
go func() { // 用新协程去执行定时任务
for { // 用上一个死循环,不停地执行,否则只会执行一次
select {
case <- ticker.C: // 时间到了就会触发这个分支的执行,其实时间到了定时器会往ticker.C 这个 channel 中写一条数据,随后被 select 捕捉到channel中有数据可读,就读取channel数据,执行相应分支的语句
printDemo()
}
}
}()
}
func main(){
// 初始化定时器,每 5s 会打印一个「demo........」
InitDemoScheduler()
// 等待,避免主线程退出,实际应用时这里可以时启动 http 服务器的监听动作,或者启动 rpc 服务的监听动作,所以不需要 sleep
time.sleep(100*time.Second)
}
case <- ticker.C
: 间到了定时器会往ticker.C
这个 channel 中写一条数据,随后被 select 捕捉到 channel 中有数据可读,就读取 channel 数据,并执行相应分支的语句,select 语法可以参考:golang中的select详解(转)
发现一种新的写法,这种写法没有用 select 语法,而是通过 for 循环从 channel 中取数,理论上应该也可以。但是没实验过,不知道行不行,
// 初始化 demo 定时器
func InitDemoScheduler() {
// 每 5 秒钟时执行一次
ticker := time.NewTicker(5 * time.Second) // 创建一个定时器
go func() { // 用新协程去执行定时任务
for _ = range ticker.C {
printDemo()
}
}()
}