5

I'm trying to write a program that will continuously call a method at a certain time interval. I'm using a cron library to try and achieve this but when I run the program it just executes and finishes with out any output.

Below is a basic example of what I'm trying to do.

Assistance greatly appreciated!

package main

import (
    "fmt"
    "github.com/robfig/cron"
)

func main() {
    c := cron.New()
    c.AddFunc("1 * * * * *", RunEverySecond)
    c.Start()
}

func RunEverySecond() {
    fmt.Println("----")
}
AFraser
  • 996
  • 4
  • 13
  • 27
  • Does this answer your question? [How best do I keep a long running Go program, running?](https://stackoverflow.com/questions/9543835/how-best-do-i-keep-a-long-running-go-program-running) – 030 Mar 17 '20 at 15:50

5 Answers5

11

You can wait for the OS to signal you, e.g. CTRL-C from the user. Also your cron expression was for every minute, i.e. only where seconds == 1.

package main

import (
    "fmt"
    "os"
    "os/signal"
    "time"

    "github.com/robfig/cron"
)

func main() {
    c := cron.New()
    c.AddFunc("* * * * * *", RunEverySecond)
    go c.Start()
    sig := make(chan os.Signal)
    signal.Notify(sig, os.Interrupt, os.Kill)
    <-sig

}

func RunEverySecond() {
    fmt.Printf("%v\n", time.Now())
}
LenW
  • 3,054
  • 1
  • 24
  • 25
6

As you can see c.Start() runs in another goroutine, so the call to c.Start returns immediately. https://github.com/robfig/cron/blob/master/cron.go#L125

So your program finishes earlier than you see any output. You may add something like time.Sleep(1 * minute) or have a close channel for this (or just <-make(chan struct{}) to wait eternally)

serejja
  • 22,901
  • 6
  • 64
  • 72
6

Using an external package for this is overkill, the time package has everything you need:

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        c := time.Tick(1 * time.Second)
        for range c {
            // Note this purposfully runs the function
            // in the same goroutine so we make sure there is
            // only ever one. If it might take a long time and
            // it's safe to have several running just add "go" here.
            RunEverySecond()
        }
    }()

    // Other processing or the rest of your program here.
    time.Sleep(5 * time.Second)

    // Or to block forever:
    //select {}
    // However, if doing that you could just stick the above for loop
    // right here without dropping it into a goroutine.
}

func RunEverySecond() {
    fmt.Println("----")
}

playground

Dave C
  • 7,729
  • 4
  • 49
  • 65
4

or something like this using sync wait group.

package main

import (
    "fmt"
    "sync"

    "github.com/robfig/cron"
)

// RunEverySecond is to run all the time.
func RunEverySecond() {
    fmt.Println("----")
    //wg.Done() // Does not release the waitgroup.
}

func main() {
    wg := &sync.WaitGroup{}
    wg.Add(1)
    c := cron.New()
    c.AddFunc("@every 1s", RunEverySecond)
    c.Start()
    wg.Wait() // This guarantees this program never exits so cron can keep running as per the cron interval.
}
smiletrl
  • 351
  • 4
  • 11
-1

Just make sure to keep the application always running, ie:

func main() {
    cronJob := cron.New()
    cronJob.Start()
    cronJob.AddFunc("* * * * * ?", PushConfigs)
    for {
    }
}
Yrineu Rodrigues
  • 1,306
  • 14
  • 12