I'm trying to write a select in Go that incorporates an optional timeout, something like this:
done := false
for !done {
if timeout > 0 {
select {
case value := <- somechannel:
// Do something with value
case <- time.After(timeout):
done = true
}
} else {
select {
case value := <- somechannel:
// Do something with value
default:
done = true
}
}
}
That is, if nothing is pending on the channel, and I haven't set a timeout, I exit. If a timeout is set and nothing is available, then I wait for either the timeout or for something to be available on the channel. I'd love to combine this into a single select, but I can't see how I can do that. Any idea?
Here is how I would implement what you want:
func foo() {
if timeout > 0 {
timer := time.NewTimer(timeout)
defer timer.Stop()
wait:
for {
select {
case value := <-somechannel:
// Do something with value
case <-timer.C:
break wait
}
}
} else {
drain:
for {
select {
case value := <-somechannel:
// Do something with value
default:
break drain
}
}
}
}
The first loop is a normal consume until timeout. The second loop drains until there are no more immediately available.