Given this code that simulates fetching of some website-stuff for 3 URL's using a fan-in pattern and range over the condensed channel: https://play.golang.org/p/MSkRI7x4vz
for s := range r {
println(s)
}
This works well, but I want to use an overall timeout signal channel, so I try to use a select in a for-loop like this: https://play.golang.org/p/LjDoIc0j-z
totalTimeout := time.After(300 * time.Millisecond)
loop:
for {
select {
case s := <-r:
fmt.Println(s)
case <-totalTimeout: // signaling usage of a channel
fmt.Println("Timed out")
break loop
}
}
}
This behaves not well: After the input channels are closed, the condensed channel from fan-in is closed. But now zero-values are read until the timeout effectively occurs. When I read http://www.tapirgames.com/blog/golang-channel or the specs https://golang.org/ref/spec#Close it seems that receiving from a closed channel "never blocks" and thus gives back zero values. I can only guess, that a range detects the close, where the select cannot, because it's condition is a read from a channel in itself.
I could break out like this
case s := <-r:
if s == "" {
break loop
}
fmt.Println(s)
Is there another approach to stop getting empty values or is this the proper idiomatic way using a select in a for loop?