Home > OS >  How to stop a periodic function in golang
How to stop a periodic function in golang

Time:02-12

So I have a function that is called after every 2 seconds. Like this

package main

import (
    "fmt"
    "time"
)

func doEvery(d time.Duration, f func(time.Time)) {
    for x := range time.Tick(d) {
        f(x)
    }
}

func helloworld(t time.Time) {
    fmt.Printf("%v: Hello, World!\n", t)
}

func main() {
    doEvery(20*time.Millisecond, helloworld)
}

Now lets say I no longer want this function to execute after every 2 seconds. Is there a way I can achieve this in golang? Or is there any better way than this to call a periodic function in golang? Thank you.

CodePudding user response:

Documentation of time.Tick() states it cannot be stopped:

Tick is a convenience wrapper for NewTicker providing access to the ticking channel only. While Tick is useful for clients that have no need to shut down the Ticker, be aware that without a way to shut it down the underlying Ticker cannot be recovered by the garbage collector; it "leaks".

If you need to stop it, use time.NewTicker() instead. Run doEvery() in a new goroutine, and pass a channel to it which gives you a mean to stop it, e.g. by closing the channel:

func doEvery(d time.Duration, done chan bool, f func(time.Time)) {
    ticker := time.NewTicker(d)
    defer ticker.Stop()

    for {
        select {
        case <-done:
            fmt.Println("Done!")
            return
        case t := <-ticker.C:
            f(t)
        }
    }
}

Testing it:

done := make(chan bool)
go doEvery(300*time.Millisecond, done, helloworld)

time.Sleep(time.Second)
close(done)

time.Sleep(time.Second)
fmt.Println("Quitting")

This will output (try it on the Go Playground):

2009-11-10 23:00:00.3  0000 UTC m= 0.300000001: Hello, World!
2009-11-10 23:00:00.6  0000 UTC m= 0.600000001: Hello, World!
2009-11-10 23:00:00.9  0000 UTC m= 0.900000001: Hello, World!
Done!
Quitting
  • Related