为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中以一定间隔同时运行多个函数

在 Go 中以一定间隔同时运行多个函数

Go
呼如林 2023-04-04 17:03:12
我有一个函数列表和它们各自的间隔。我想同时运行每个函数的时间间隔。在 JavaScript 中,我写了类似这样的东西:maps.forEach(({fn, interval}) => {     setInterval(fn, interval) })我如何在 Golang 中实现此功能?
查看完整描述

1 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

使用 atime.Ticker定期接收“事件”,您可以使用它来为函数的执行计时。time.Ticker您可以通过致电获得time.NewTicker()。返回的代码有一个定期发送值的通道。

使用 goroutine 连续接收事件并调用函数,例如使用循环for range

让我们看看 2 个函数:

func oneSec() {

    log.Println("oneSec")

}


func twoSec() {

    log.Println("twoSec")

}

这是一个定期调用给定函数的简单调度程序:


func schedule(f func(), interval time.Duration) *time.Ticker {

    ticker := time.NewTicker(interval)

    go func() {

        for range ticker.C {

            f()

        }

    }()

    return ticker

}

使用它的例子:


func main() {

    t1 := schedule(oneSec, time.Second)

    t2 := schedule(twoSec, 2*time.Second)

    time.Sleep(5 * time.Second)

    t1.Stop()

    t2.Stop()

}

示例输出(在Go Playground上尝试):


2009/11/10 23:00:01 oneSec

2009/11/10 23:00:02 twoSec

2009/11/10 23:00:02 oneSec

2009/11/10 23:00:03 oneSec

2009/11/10 23:00:04 twoSec

2009/11/10 23:00:04 oneSec

请注意,Ticker.Stop()不会关闭代码通道,因此 afor range不会终止;Stop()仅停止在代码通道上发送值。


如果您想终止用于安排函数调用的 goroutine,您可以使用额外的通道来完成。然后那些 goroutines 可能会使用一个select语句来“监控”ticker 的频道和这个done频道,如果从中接收done成功则返回。


例如:


func schedule(f func(), interval time.Duration, done <-chan bool) *time.Ticker {

    ticker := time.NewTicker(interval)

    go func() {

        for {

            select {

            case <-ticker.C:

                f()

            case <-done:

                return

            }

        }

    }()

    return ticker

}

并使用它:


func main() {

    done := make(chan bool)

    t1 := schedule(oneSec, time.Second, done)

    t2 := schedule(twoSec, 2*time.Second, done)

    time.Sleep(5 * time.Second)

    close(done)

    t1.Stop()

    t2.Stop()

}

请注意,即使在这个简单的示例中没有必要停止代码(因为当maingoroutine 结束时,程序也会结束),在现实生活中,如果应用程序继续运行,让代码不停止会浪费资源(它们会继续使用后台 goroutine,并将继续尝试在他们的频道上发送值)。

最后的话:

如果您有一段函数区间对,只需使用循环将每一对传递给此schedule()函数即可。是这样的:

type pair struct {

    f        func()

    interval time.Duration

}


pairs := []pair{

    {oneSec, time.Second},

    {twoSec, 2 * time.Second},

}


done := make(chan bool)

ts := make([]*time.Ticker, len(pairs))

for i, p := range pairs {

    ts[i] = schedule(p.f, p.interval, done)

}


time.Sleep(5 * time.Second)

close(done)


for _, t := range ts {

    t.Stop()

}


查看完整回答
反对 回复 2023-04-04
  • 1 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信