Recently I saw a post in Reddit asking how to accomplish parallel network calls in Go. This seemed like a really fun example of how Go makes asynchronous tasks like this readable, ie. not too brain-twisty.
The below code takes a slice of URLs and GETs their response bodies in parallel. For brevity i'll leave out the HTTP call.
Some of the essential pieces are:
sync.WaitGroup - blocks until all goroutines are finished, as it determines through the number of calls WaitGroup.Done()
go func - calls the following inline function in a new goroutine.
resultChan is a buffered channel, capacity (the second argument accounts for how many messages are expected to be sent through the channel. Note: a mismatch will cause a deadlock. This is good, ideally, everything should be accounted for.
defer executes waitGroup.Done after the enclosing function.
func CheckAll() []string {
var waitGroup sync.WaitGroup
urls := []string{
"https://www.google.com",
"https://www.microsoft.com",
"https://www.amazon.com",
}
waitGroup.Add(len(urls))
resultChan := make(chan string, len(urls))
for _, toCheck := range urls {
go func(url string) {
defer waitGroup.Done()
body := doGet(url)
resultChan <- body
}(toCheck)
}
waitGroup.Wait()
close(resultChan)
results := chanToSlice(resultChan)
return results
}
func chanToSlice(c chan string) []string {
s := make([]string, 0)
for i := range c {
s = append(s, i)
}
return s
}