Real life concurrency in Go
matt.aimonetti.net
matt.aimonetti.net
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. ch := make(chan *HttpResponse, len(urls)) // buffered
can just be ch := make(chan *HttpResponse)
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. 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
} Go implements OOP slightly differently than other
languages. Functions are defined on an interface,
not a class or subclass.
This is not quite correct. Functions are defined on concrete types. Interfaces are named collections of functions, used to describe behavior.