[go] 반복적 인 작업을 주기적으로 수행하는 방법이 있습니까?

Go에서 반복적 인 백그라운드 작업을 수행 할 수있는 방법이 있습니까? Timer.schedule(task, delay, period)Java 와 같은 것을 생각하고 있습니다. 나는 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)
}



답변

이 기능 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)..


답변

어때요?

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")
}

운동장


답변

틱 시프 팅에 신경 쓰지 않고 (각 실행에 얼마나 오래 걸 렸는지에 따라) 채널을 사용하지 않으려는 경우 기본 범위 기능을 사용할 수 있습니다.

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")
    }
}

운동장


답변

이 라이브러리를 확인하십시오 : 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()


답변

이 질문에 대한 더 넓은 대답은 Occam에서 자주 사용되며 JCSP 를 통해 Java 커뮤니티에 제공되는 레고 브릭 접근법을 고려할 수 있습니다 . 피터 웰치 (Peter Welch) 는이 아이디어에 대해 매우 훌륭한 발표를 합니다.

Go는 Occam과 동일한 커뮤니 케이 팅 순차 프로세스 기본 사항을 사용하므로이 플러그 앤 플레이 방식은 Go로 직접 변환됩니다.

따라서 반복적 인 작업을 설계 할 때 채널을 통해 이벤트 (예 : 메시지 또는 신호)를 교환하는 간단한 구성 요소 (고 루틴)의 데이터 흐름 네트워크로 시스템을 구축 할 수 있습니다.

이 접근 방식은 구성 적입니다. 각 소규모 구성 요소 그룹은 그 자체로 더 큰 구성 요소로 작동 할 수 있습니다. 복잡한 동시 시스템은 이해하기 쉬운 벽돌로 만들어지기 때문에 매우 강력 할 수 있습니다.

각주 : Welch의 프레젠테이션에서 그는 채널에 Occam 구문을 사용합니다 . 그리고 ? 이들은 Go의 ch <-<-ch 에 직접 대응됩니다 .


답변

다음 코드를 사용합니다.

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")
}

더 간단하고 나에게 잘 작동합니다.


답변

당신은 순간 시세 에서 그것을 중지하려는 경우

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")
}