It's a bit odd to do the time.Sleep in this code because it means that select is often not able to receive on the ch channel:
select {
case r := <-ch:
fmt.Printf("%s was fetched\n", r.url)
responses = append(responses, r)
if len(responses) == len(urls) {
return responses
}
default:
fmt.Printf(".")
time.Sleep(5e7)
}
It would be better to use time.Tick
ticker := time.Tick(50 * time.Millisecond)
select {
case r := <-ch:
fmt.Printf("%s was fetched\n", r.url)
responses = append(responses, r)
if len(responses) == len(urls) {
return responses
}
case <-ticker:
fmt.Printf(".")
}
Also, there's no need to use a buffered channel. Each goroutine that's handling a URL get can just wait for the send on the channel before terminating.
And another thing that could be done is to not have asyncHttpGets return a slice of *HttpResponse but have it return a channel and then range over it. Then asyncHttpGets could run in its own goroutine and just close the channel when done.
This is indeed what Go is great for. But your code example is a bit wonky :) Specifically,
for {
select {
case r := <-ch:
// do something with r
default:
fmt.Printf(".")
time.Sleep(5e7)
}
}
You're needlessly blocking 50ms on every iteration. (Side note: time.Sleep(50 * time.Millisecond) better captures your intent.) Better to reformulate that as
for {
select {
case r := <-ch:
// do something with r
case <-time.After(50*time.Millisecond):
fmt.Printf(".")
}
}
Or, if you don't need the dots in the output,
for i := 0; i < cap(ch); i++ {
r := <-ch
// do something with r
}
5 comments
[ 135 ms ] story [ 909 ms ] thread