One somewhat critical point with channels and select
loops that we haven't examined particularly closely is the ability—and often necessity—to kill a select
loop after a certain timeout.
Many of the applications we've written so far are long-running or perpetually-running, but there are times when we'll want to put a finite time limit on how long goroutines can operate.
The for { select { } }
switch we've used so far will either live perpetually (with a default case) or wait to be broken from one or more of the cases.
There are two ways to manage interval-based tasks—both as part of the time package, unsurprisingly.
The time.Ticker
struct allows for any given operation after the specified period of time. It provides C, a blocking channel that can be used to detect activity sent after that period of time; refer to the following code:
package main import ( "log" "time" ) func main() { timeout := time.NewTimer(5 * time.Second) defer log.Println("Timed out!") for { select { case <-timeout.C: return default: } } }
We can extend this to end channels and concurrent execution after a certain amount of time. Take a look at the following modifications:
package main import ( "fmt" "time" ) func main() { myChan := make(chan int) go func() { time.Sleep(6 * time.Second) myChan <- 1 }() for { select { case <-time.After(5 * time.Second): fmt.Println("This took too long!") return case <-myChan: fmt.Println("Too little, too late") } } }
18.188.218.157