Channels, Timeouts, and Tickers
This lesson explains how to set the responses of goroutines with time as a controlling factor.
We'll cover the following
The time
package has some interesting functionality to use in combination with channels.
It contains a struct time.Ticker
, which is an object that repeatedly sends a time value on a contained channel C
at a
specified time interval:
type Ticker struct {
C <-chan Time // the channel on which the ticks are delivered.
// contains filtered or unexported fields
...
}
A Ticker
can be very useful when, during the execution of goroutines, something (logging a status, a printout, a calculation, and so on) has to be done periodically at a certain time interval. It is stopped with Stop()
; use this in a defer
statement. All this fits nicely in a select statement:
ticker := time.NewTicker(updateInterval)
defer ticker.Stop()
...
select {
case u:= <- ch1:
...
case v:= <- ch2:
...
case <- ticker.C:
logState(status) // e.g. call some logging function logState
default: // no value ready to be received
...
}
The time.Tick()
function with signature func Tick(d Duration) <-chan Time
is useful when you only need access to the return channel and don’t need to shut it down. It sends out the time on the return channel with periodicity d
, which is a number of nanoseconds. It is handy to use when you have to limit the rate of processing per unit time like in the following code snippet (the function client.Call( )
is an RPC-call, the details are not further specified here):
import "time"
rate_per_sec := 10
var dur Duration = 1e9 / rate_per_sec
chRate := time.Tick(dur) // a tick every 1/10th of a second
for req := range requests {
<- chRate // rate limit our Service.Method RPC calls
go client.Call("Service.Method", req, ...)
}
The net effect is that new requests are only handled at the indicated rate, which means the channel chRate
blocks higher rates. The rate per second can be increased or decreased according to the load and / or the resources of the machine.
A tick
type looks exactly the same as a Ticker
type (it is constructed with time.Tick(d Duration)
), but it sends the time only once, after a Duration d
. There is also a function time.After(d)
with the signature: func After(d Duration) <-chan Time
. After Duration d
, the current time is sent on the returned channel; this is equivalent to NewTimer(d).C
It resembles Tick()
, but After()
sends the time only once. The following listing shows a concrete example, and also nicely illustrates the default
clause in select
:
Get hands-on with 1400+ tech skills courses.