I have a loop that iterates until a job is up and running:
ticker := time.NewTicker(time.Second * 2)
defer ticker.Stop()
started := time.Now()
for now := range ticker.C {
job, err := client.Job(jobID)
switch err.(type) {
case DoesNotExistError:
continue
case InternalError:
return err
}
if job.State == "running" {
break
}
if now.Sub(started) > time.Minute*2 {
return fmt.Errorf("timed out waiting for job")
}
}
Works great in production. The only problem is that it makes my tests slow. They all wait at least 2 seconds before completing. Is there anyway to get time.Tick
to tick immediately?
Unfortunately, it seems that Go developers will not add such functionality in any foreseeable future, so we have to cope...
There are two common ways to use tickers:
for
loopGiven something like this:
ticker := time.NewTicker(period)
defer ticker.Stop()
for <- ticker.C {
...
}
Use:
ticker := time.NewTicker(period)
defer ticker.Stop()
for ; true; <- ticker.C {
...
}
for
-select
loopGiven something like this:
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
ticker := time.NewTicker(period)
defer ticker.Stop()
loop:
for {
select {
case <- ticker.C:
f()
case <- interrupt:
break loop
}
}
Use:
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
ticker := time.NewTicker(period)
defer ticker.Stop()
loop:
for {
f()
select {
case <- ticker.C:
continue
case <- interrupt:
break loop
}
}
time.Tick()
?If you're using Go 1.23+, you can safely use time.Tick()
instead.
Before Go 1.23:
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".
After Go 1.23:
Before Go 1.23, this documentation warned that the underlying
Ticker
would never be recovered by the garbage collector, and that if efficiency was a concern, code should useNewTicker
instead and callTicker.Stop
when the ticker is no longer needed. As of Go 1.23, the garbage collector can recover unreferenced tickers, even if they haven't been stopped. TheStop
method is no longer necessary to help the garbage collector. There is no longer any reason to preferNewTicker
whenTick
will do.