Skip to content

Instantly share code, notes, and snippets.

@sethmcl
Created August 9, 2016 21:05
Show Gist options
  • Select an option

  • Save sethmcl/00d3d1fda97e57b4d725006eb49129c1 to your computer and use it in GitHub Desktop.

Select an option

Save sethmcl/00d3d1fda97e57b4d725006eb49129c1 to your computer and use it in GitHub Desktop.
Simple example of goroutines and channels
package main
import (
"fmt"
"net/http"
)
const maxConcurrentRequests = 100
type Response struct {
url string
httpStatus int
}
func asyncGET(urls []string) []*Response {
var responses []*Response
semaphore := make(chan int, maxConcurrentRequests)
results := make(chan *Response)
client := http.Client{}
for _, url := range urls {
go func(url string) {
fmt.Printf("QUEUE %s\n", url)
// Try to add a value to the semaphore channel
// If channel is full, then this code will block
semaphore <- 0
// Run HTTP GET request
resp, _ := client.Get(url)
defer resp.Body.Close()
// Return response to channel
results <- &Response{url, resp.StatusCode}
// Pull one item from semaphore channel, to open up space for
// next request
<-semaphore
}(url)
}
for {
select {
case r := <-results:
// Read a Response from the results channel
fmt.Printf("HTTP %d %s\n", r.httpStatus, r.url)
responses = append(responses, r)
if len(responses) == len(urls) {
return responses
}
}
}
}
func generateURLs(count int) []string {
urls := make([]string, count)
base := "https://duckduckgo.com/"
for idx := range urls {
urls[idx] = fmt.Sprintf("%s?q=%d", base, idx)
}
return urls
}
func main() {
urls := generateURLs(100)
results := asyncGET(urls)
fmt.Printf("DONE. Got %d responses!", len(results))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment