有没有一种方法可以每隔一段时间做重复的工作?

有没有办法在围棋中做重复的后台任务?我想到的是Java中的Timer.schedule(task, delay, period)。我知道我可以用goroutine和Time.sleep()来做这件事,但我想要一些容易停止的东西。

这是我得到的,但在我看来很难看。有更干净/更好的方法吗?

func oneWay() {
var f func()
var t *time.Timer


f = func () {
fmt.Println("doing stuff")
t = time.AfterFunc(time.Duration(5) * time.Second, f)
}


t = time.AfterFunc(time.Duration(5) * time.Second, f)


defer t.Stop()


//simulate doing stuff
time.Sleep(time.Minute)
}
147978 次浏览

像这样的怎么样?

package main


import (
"fmt"
"time"
)


func schedule(what func(), delay time.Duration) chan bool {
stop := make(chan bool)


go func() {
for {
what()
select {
case <-time.After(delay):
case <-stop:
return
}
}
}()


return stop
}


func main() {
ping := func() { fmt.Println("#") }


stop := schedule(ping, 5*time.Millisecond)
time.Sleep(25 * time.Millisecond)
stop <- true
time.Sleep(25 * time.Millisecond)


fmt.Println("Done")
}

操场

功能time.NewTicker建立发送周期性消息的通道,并提供停止该通道的方法。像这样使用它(未测试):

ticker := time.NewTicker(5 * time.Second)
quit := make(chan struct{})
go func() {
for {
select {
case <- ticker.C:
// do stuff
case <- quit:
ticker.Stop()
return
}
}
}()

您可以通过关闭quit通道:close(quit)来停止工作进程。

这个问题的更广泛的答案可能是考虑在OCCAM中经常使用的乐高积木方法,并通过JCSP提供给Java社区。关于这个想法,有一个非常好的彼得·韦尔奇的演讲

这种即插即用的方法可以直接转换为Go,因为Go使用与Occam相同的通信顺序过程基本原理。

因此,在设计重复性任务时,您可以将系统构建为通过通道交换事件(即消息或信号)的简单组件(如goroutine)的数据流网络。

这种方法是组合的:每一组小组件本身可以表现为一个更大的组件,无穷无尽。这可能非常强大,因为复杂的并发系统是由易于理解的砖块组成的。

脚注:在Welch的演讲中,他对通道使用了Occam语法,即,这些直接对应于Go中的ch<;-<;-ch

查看此库:https://github.com/robfig/cron

示例如下:

c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()

如果您不关心分笔成交点移位(取决于之前每次执行所花费的时间),并且您不想使用通道,则可以使用本机范围函数。

package main


import "fmt"
import "time"


func main() {
go heartBeat()
time.Sleep(time.Second * 5)
}


func heartBeat() {
for range time.Tick(time.Second * 1) {
fmt.Println("Foo")
}
}

操场

如果你想在任何时候停止它,股票代码

ticker := time.NewTicker(500 * time.Millisecond)
go func() {
for range ticker.C {
fmt.Println("Tick")
}
}()
time.Sleep(1600 * time.Millisecond)
ticker.Stop()

如果您不想停止它,请标记号于

tick := time.Tick(500 * time.Millisecond)
for range tick {
fmt.Println("Tick")
}

我使用以下代码:

package main


import (
"fmt"
"time"
)


func main() {
now := time.Now()
fmt.Println("\nToday:", now)


after := now.Add(1 * time.Minute)
fmt.Println("\nAdd 1 Minute:", after)


for {
fmt.Println("test")
time.Sleep(10 * time.Second)


now = time.Now()


if now.After(after) {
break
}
}


fmt.Println("done")
}

它更简单,对我来说很好。

你可以像这样简单地使用gocron包:

package main


import (
"fmt"
"time"
// go get github.com/go-co-op/gocron
"github.com/go-co-op/gocron"
)


func main() {
s := gocron.NewScheduler(time.UTC)
s.Every(3).Seconds().Do(func() { fmt.Println("Every 3 seconds") })
// you can start running the scheduler in two different ways:
// starts the scheduler asynchronously
s.StartAsync()
// starts the scheduler and blocks current execution path
// s.StartBlocking()
}

GOCRON:https://github.com/go-co-op/gocron