Middle+
Tâche : « Traitement parallèle des URL avec limite de temps » Écrivez une fonction fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, qui : 1. Pour chaque URL, effectue une requête HTTP GET (peut utiliser http.Get). 2. Retourne un map[string]string, où la clé est l'URL, et la valeur est le corps de la réponse (en chaîne) ou une chaîne vide en cas d'erreur/timeout. 3. Au maximum, maxParallel requêtes sont exécutées simultanément. 4. La durée totale de la fonction ne doit pas dépasser timeout. Si le délai est écoulé, toutes les requêtes non terminées sont annulées, et la fonction retourne ce qu'elle a pu. 5. Utilisez le contexte pour l'annulation.
sobes.tech IA
Réponse de l'IA
go package main
import ( "context" "io/ioutil" "net/http" "sync" "time" )
func fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel()
results := make(map[string]string)
var mu sync.Mutex
sem := make(chan struct{}, maxParallel) // sémaphore pour limiter le parallélisme
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // réserver une place
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // libérer la place
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
if err != nil {
mu.Lock()
results[u] = ""
mu.Unlock()
return
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
mu.Lock()
results[u] = ""
mu.Unlock()
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
mu.Lock()
results[u] = ""
mu.Unlock()
return
}
mu.Lock()
results[u] = string(body)
mu.Unlock()
}(url)
}
}
wg.Wait()
return results
}