"for-select" is very important in golang for non-blocking operation. "Timer" is a good partner with for-select to handle timeout and performance issue.
In this post, I show some use cases, how for-select with timer work together.
Timeout
Listen to 2 channels, if no receive from any channel in 1s, it goes to the timeout case
for {
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
case <-time.After(time.Second):
// timeout, do something
}
}
Interval
Sometimes we can see new gophers write the following code:
for {
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
default:
// always non-block here,
}
// no interval, run this for-loop intensively
}
Then most of usage CPU maybe occupied because of intensive non-blocking infinite loop. We could use timeout case to avoid it, or add interval to entire for loop like this.
for {
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
default:
}
<-time.After(time.Second) // or time.sleep(time.Second)
}
The for loop now has 1s interval.
Timer
Sometimes we would like to set timer to break for-loop.
You may implement like following code:
t := time.NewTimer(time.Second * 5)
loop:
for {
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
case <-time.After(time.Millisecond *500):
case <-t.C:
break loop
}
}
The code works, but there's a potential issue in this implementation. Be careful, "select" statement chooses any non-blocked case randomly, for example, even if the timer is fired, select can pick up another cases when they're non-blocked.
So we can improve it by adding another select statement.
t := time.NewTimer(time.Second * 5)
loop:
for {
select {
case <-t.C: // if timer is fired, break the loop
break loop
default: // timer is not fired, non-blocked
}
select {
case a := <-ch1:
fmt.Println(a)
case b := <-ch2:
fmt.Println(b)
case <-time.After(time.Millisecond *500):
}
}
I think these are common use cases for for-select with Timer.
If any mistake and question, please feel free to write comments.
Top comments (0)