问题描述
我正在通过制定任务计划来学习Go-lang.我使用的 cron库接受cron表达式和func作为添加调度程序的参数.
I'm studying go-lang by developing a task schedular. The cron library I use accepts a cron expression and a func as parameters to add a scheduler.
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
我正在开发的计划表根据yaml文件计划作业.因此,我迭代作业以添加时间表,如下所示:
The schedular I am developing schedules jobs according to a yaml file. So I iterate the jobs to add schedulars like this:
type Job struct {
Name string
Interval string
}
func DistributeJob(job Job) {
log.Println("running", job, job.Interval)
}
func main() {
//load config from yaml
c := cron.New()
for _, job := range config.Jobs {
c.AddFunc("@every "+job.Interval, func() {
DistributeJob(job)
})
log.Println("Job " + job.Name + " has been scheduled!")
}
c.Start()
select {}
}
所有作业均按其间隔安排,但事实证明,它们正在打印最后一个作业的描述.例如,如果我计划两个作业,则第一个间隔为3分钟,而后一个间隔为1分钟.控制台将打印:
All jobs are scheduled on their intervals but it turns out that they're printing the last job's description. For example, if I schedule two jobs, the first interval on 3min and the latter interval on 1min. The console prints:
12:01: Running latter 1min
12:02: Running latter 1min
12:03: Running latter 1min
12:03: Running latter 1min//this one should be the first job
我认为问题出在
func() {
DistributeJob(job)
})
似乎只需要最后一份工作,但我不知道为什么.我尝试使用
It seems it only takes the last job but I can't figure out why. I tried using
c.AddFunc("@every "+job.Interval, func(job JobType) {
DistributeJob(job)
}(job))
但由于无法用作值而失败
but it fails due to cannot used as value
推荐答案
虽然您没有使用goroutine,但您犯的错误几乎与此处描述的错误相同: https://github.com/golang/go/wiki/CommonMistakes#using-closures-with-goroutines
While you are not using goroutines, the mistake you are making is almost identical to the one described here: https://github.com/golang/go/wiki/CommonMistakes#using-closures-with-goroutines
引用:
因此,您尝试进行的修复(将其作为参数传递给函数)将在原则上解决该问题,但是您无法将具有参数的函数传递给cron库-具有参数的函数与不带(除了添加()
之外,您实际上是在预先调用该函数并尝试传递其返回值.)
So your attempted fix (to pass it as a parameter to your function) would in principle fix the problem, however you cannot pass a function with parameters to the cron library - a function with parameters is a different type from one without (in addition to which by adding the ()
you are actually calling the function in advance and trying to pass its return value).
最简单的解决方法是为循环的每次迭代创建一个新变量,从而避免整个问题,就像这样:
The simplest fix is to create a new variable for every iteration of the loop and avoid the whole problem, like so:
for _, job := range config.Jobs {
realJob := job // a new variable each time through the loop
c.AddFunc("@every "+realJob.Interval, func() {
DistributeJob(realJob)
})
log.Println("Job " + realJob.Name + " has been scheduled!")
}
这篇关于无法在for循环中将变量分配给匿名函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!