Skip to content

Instantly share code, notes, and snippets.

@samuraisam
Created July 29, 2012 00:20
Show Gist options
  • Select an option

  • Save samuraisam/3195413 to your computer and use it in GitHub Desktop.

Select an option

Save samuraisam/3195413 to your computer and use it in GitHub Desktop.
trying out the select functionality of go
/*
* Intent - in paralell, download a series of urls
* - timeout after 1 sec if the download has not completed
* - allow for failures, and move on (similar to timeout)
* - collect the stringified response from the fetched url
*/
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
func main() {
var urls = []string{
"http://ssutch.org",
"http://reddit.com",
"http://news.ycombinator.com",
"http://slashdot.org",
"http://google.com",
"http://samuraifilms.org",
"http://gmail.com",
}
errors := make(chan string)
messages := make(chan string)
finished := make(chan bool)
// downloaad all the things
var waiter sync.WaitGroup
go func() {
// start downloading all urls
for _, u := range urls {
waiter.Add(1) // tell waiter we are downloading something
go downloadUrl(u, messages, errors, waiter) // fire off downloadUrl
}
// wait for everything to finish
log.Print("waiting for things to finish")
waiter.Wait()
log.Print("far as we know, things finished") // XXX: NEVER GETS HERE!
// when done, send finished
finished <- true
}()
// loop forever waiting for responses
for {
select {
case err := <-errors:
// we got an error, d'aw
log.Print("error fetching: ", err)
case msg := <-messages:
// we got a message, a successful url, yay!
log.Print("got message length: ", len(msg))
case <-finished:
// called when the waitgroup finishes (errors or not)
log.Print("all finished!")
break
}
}
}
func downloadUrl(url string, messages chan string, errors chan string, wg sync.WaitGroup) {
// TODO: timeout after 1 sec
defer func() {
log.Print("telling WaitGroup we are done downloading")
wg.Done() // when we are done, tell the waitgroup that we are
}()
resp, err := http.Get(url) // get the url
if err != nil {
errors <- fmt.Sprintf("error getting: ", err) // send the url getting error
return
}
val, err := ioutil.ReadAll(resp.Body) // read the body
if err != nil {
errors <- fmt.Sprintf("error reading: ", err) // send the read error
return
} else {
log.Print("sending value")
messages <- string(val) // finally send the stringified response body
log.Print("sent value")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment