安装Cronexpr包:
go get -u github.com/gorhill/cronexpr
这个包支持七位时间控制
*(秒) *(分) *(时) *(日) *(月) *(周) *(年)
栗子:
每5秒执行一次: */5 * * * * * *
一个简单的小栗子
package main import ( "fmt" "github.com/gorhill/cronexpr" "time" ) //* * * * * * * //秒 分 时 日 月 周 年 func main() { var expr *cronexpr.Expression var err error //每5秒执行一次 if expr, err = cronexpr.Parse("*/5 * * * * * *");err != nil{ fmt.Println("err=", err) return } //当前时间 now := time.Now() fmt.Println("now=",now) nextTime := expr.Next(now) fmt.Println("nextTime=", nextTime) time.AfterFunc(nextTime.Sub(now), func() { fmt.Println("被调用了") }) time.Sleep(6*time.Second) }
输出
now= 2020-05-03 00:58:48.6350048 +0800 CST m=+0.008000001 nextTime= 2020-05-03 00:58:50 +0800 CST 被调用了
注意:这里每5秒也好,每3分钟也好,都不是以现在的时间计时的:
例如:
每5秒:假设现在12:00:02,下次执行时间将会是12:00:05,他会从0秒开始累加计算下次时间,而不是现在的秒数
每3分钟:假设现在12:00:02,下次执行时间将会是12:03:00,他会从0分开始累加计算,并且秒数归零
一个并发多任务的定时任务小案例
package main import ( "fmt" "github.com/gorhill/cronexpr" "time" ) //代表任务 type CronJob struct { expr *cronexpr.Expression nextTime time.Time } func main() { //创建map,用于存储多个定时任务 scheduleTable := make(map[string]*CronJob) //当前时间 now := time.Now() expr, _ := cronexpr.Parse("*/5 * * * * * *") cronJob := &CronJob{ expr:expr, nextTime:expr.Next(now), } scheduleTable["job1"] = cronJob expr, _ = cronexpr.Parse("*/4 * * * * * *") cronJob = &CronJob{ expr:expr, nextTime:expr.Next(now), } scheduleTable["job2"] = cronJob go func() { for{ now := time.Now() //遍历map,取出每一个定时任务,检查是否过期 for jobName, cronJob := range scheduleTable{ //当前定时任务下次执行的时间在当前时间之前或者等于当前时间 if cronJob.nextTime.Before(now)||cronJob.nextTime.Equal(now){ //开启协程,执行定时任务 go func(jobName string) { fmt.Println("执行:", jobName) }(jobName) //计算下一次调度的时间 cronJob.nextTime = cronJob.expr.Next(now) fmt.Println(jobName, "下次执行时间:",cronJob.nextTime) } } select { case <-time.NewTimer(100 * time.Millisecond).C: } } }() time.Sleep(100*time.Second) }