Voici un exemple de mise en place d'un téléchargeur concurrent. Les éléments à prendre en compte sont la bande passante, la mémoire et l'espace disque. Vous pouvez détruire votre bande passante en essayant d'en faire trop à la fois, et il en va de même pour la mémoire. Vous téléchargez des fichiers assez volumineux, la mémoire peut donc être un problème. Une autre chose à noter est qu'en utilisant les gorountines, vous perdez l'ordre des requêtes. Ainsi, si l'ordre des octets retournés a de l'importance, cela ne fonctionnera pas car vous devrez connaître l'ordre des octets pour assembler le fichier à la fin, ce qui signifierait qu'un téléchargement un par un est préférable, à moins que vous n'implémentiez un moyen de garder une trace de l'ordre (peut-être une sorte de map[order int][]bytes globale avec mutex pour éviter les conditions de course). Une alternative qui n'implique pas Go
(en supposant que vous ayez une machine Unix pour plus de facilité) est d'utiliser Curl
voir ici http://osxdaily.com/2014/02/13/download-with-curl/
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sync"
)
// now your going to have to be careful because you can potentially run out of memory downloading to many files at once..
// however here is an example that can be modded
func downloader(wg *sync.WaitGroup, sema chan struct{}, fileNum int, URL string) {
sema <- struct{}{}
defer func() {
<-sema
wg.Done()
}()
client := &http.Client{Timeout: 10}
res, err := client.Get(URL)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var buf bytes.Buffer
// I'm copying to a buffer before writing it to file
// I could also just use IO copy to write it to the file
// directly and save memory by dumping to the disk directly.
io.Copy(&buf, res.Body)
// write the bytes to file
ioutil.WriteFile(fmt.Sprintf("file%d.txt", fileNum), buf.Bytes(), 0644)
return
}
func main() {
links := []string{
"url1",
"url2", // etc...
}
var wg sync.WaitGroup
// limit to four downloads at a time, this is called a semaphore
limiter := make(chan struct{}, 4)
for i, link := range links {
wg.Add(1)
go downloader(&wg, limiter, i, link)
}
wg.Wait()
}