package main import ( "flag" "fmt" "io" "io/ioutil" "log" "net/http" "runtime" "sort" "sync" ) const max = 1000 type pair struct { u string s int64 } type pairs []pair func (p pairs) Len() int { return len(p) } func (p pairs) Swap(a, b int) { p[a], p[b] = p[b], p[a] } func (p pairs) Less(a, b int) bool { return p[a].s < p[b].s } var workers = flag.Int("workers", runtime.NumCPU()*4, "number of downloaders") func main() { flag.Parse() for r := range srt(attack(urls(max), *workers)) { fmt.Printf("%v\t%v\n", r.s, r.u) } } func urls(max int) chan string { r := make(chan string) go func() { for i := 0; i < max; i++ { r <- fmt.Sprintf("https://hmm.clstr.co/size/%03d", i) } close(r) }() return r } func attack(urls chan string, workers int) chan pair { r := make(chan pair) go func() { c := http.Client{} s := make(chan bool, workers) wg := sync.WaitGroup{} for u := range urls { wg.Add(1) s <- true go func(url string) { resp, err := c.Get(url) if err != nil { log.Printf("probalo: %v", err) return } r <- pair{url, resp.ContentLength} if n, err := io.Copy(ioutil.Discard, resp.Body); err != nil { log.Printf("after %v bytes: %v", n, err) } if err := resp.Body.Close(); err != nil { log.Printf("close body: %v", err) } <-s wg.Done() }(u) } wg.Wait() close(r) }() return r } func srt(in chan pair) chan pair { r := make(chan pair) go func() { ps := pairs{} for r := range in { ps = append(ps, r) } sort.Sort(ps) for _, p := range ps { r <- p } close(r) }() return r } func print() { for i := 0; i < 1000; i++ { fmt.Sprintf("hmm.clstr.co/size/%03d", i) } }