无法在for循环中将变量分配给匿名函数

无法在for循环中将变量分配给匿名函数

本文介绍了无法在for循环中将变量分配给匿名函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过制定任务计划来学习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循环中将变量分配给匿名函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 03:33