Skip to content

Instantly share code, notes, and snippets.

@bentranter
Last active September 3, 2015 16:37
Show Gist options
  • Save bentranter/04e989683eb796f6f775 to your computer and use it in GitHub Desktop.
Save bentranter/04e989683eb796f6f775 to your computer and use it in GitHub Desktop.
Async vs. Sync HTTP requests
// This tries to show the difference between async and sync
// HTTP GET requests. Big surprise: its way faster do this
// async...
package main
import (
"fmt"
"github.com/bentranter/chalk"
"net/http"
"time"
)
var urls = []string{
"https://github.com",
"https://google.ca",
"https://twitter.com",
"http://golang.org",
"http://ninesummers.com",
"https://facebook.com",
"https://yahoo.com",
"http://metalab.co",
"https://reddit.com",
"https://youtube.com",
"https://amazon.com",
"https://wikipedia.org",
"https://linkedin.com",
"https://bing.com",
"https://instagram.com",
"https://microsoft.com",
"https://msn.com",
"https://wordpress.com",
"https://tumblr.com",
}
// HTTPResponse is the struct that holds our response
// data
type HTTPResponse struct {
url string
response *http.Response
err error
}
func asyncHTTPGet(urls []string) []*HTTPResponse {
start := time.Now()
ch := make(chan *HTTPResponse)
responses := []*HTTPResponse{}
for _, url := range urls {
go func(url string) {
fmt.Printf("Fetching %s \n", url)
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error: ", err)
}
defer resp.Body.Close()
ch <- &HTTPResponse{url, resp, err}
}(url)
}
for {
select {
case r := <-ch:
fmt.Printf("%s | %s was fetched\n", time.Since(start), r.url)
responses = append(responses, r)
if len(responses) == len(urls) {
return responses
}
}
}
return responses
}
func syncHTTPGet(urls []string) []*HTTPResponse {
start := time.Now()
responses := []*HTTPResponse{}
for _, url := range urls {
fmt.Printf("Fetching %s \n", url)
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error: ", err)
}
defer resp.Body.Close()
fmt.Printf("%s | %s was fetched\n", time.Since(start), url)
responses = append(responses, &HTTPResponse{url, resp, err})
}
return responses
}
func main() {
fmt.Println(chalk.Blue("*** ASYNC ***"))
results := asyncHTTPGet(urls)
for _, result := range results {
fmt.Printf("%s status, %s\n", result.url, result.response.Status)
}
fmt.Println(chalk.Blue("\n\n*** SYNC ***"))
results = syncHTTPGet(urls)
for _, result := range results {
fmt.Printf("%s status, %s\n", result.url, result.response.Status)
}
}
@bentranter
Copy link
Author

Before anyone points it out: yes, I know that if an HTTP req fails, we'll get that classic error everyone knows and loves panic: runtime error: invalid memory address or nil pointer dereference since I don't break out of the loop at line 48 if the error isn't nil.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment