当前位置:  开发笔记 > 编程语言 > 正文

在Go中间隔地同时运行多个函数

如何解决《在Go中间隔地同时运行多个函数》经验,为你挑选了1个好方法。

我有一个功能列表和它们各自的间隔.我想同时以其间隔运行每个函数.

在JavaScript中,我写了类似的东西:

maps.forEach(({fn, interval}) => {
    setInterval(fn, interval)
})

如何在Golang中实现此功能?



1> icza..:

使用a time.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()不会关闭自动收报机的通道,因此for range不会终止; Stop()只停止在自动收报机的频道上发送值.

如果要终止用于计划函数调用的goroutines,可以使用其他通道执行此操作.然后那些goroutines可以使用一个select语句来"监控"自动收报机的频道和这个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()
}

在Go Playground尝试这个.

请注意,即使在这个简单的示例中不需要停止代码(因为当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()
}

在Go Playground尝试这个.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有