Middle+
Compito: «Elaborazione parallela di URL con limite di tempo» Scrivi una funzione fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, che: 1. Per ogni URL esegue una richiesta HTTP GET (si può usare http.Get). 2. Restituisce una mappa[string]string, dove la chiave è l'URL e il valore è il corpo della risposta (come stringa) o una stringa vuota in caso di errore/timeout. 3. Non vengono eseguite più di maxParallel richieste contemporaneamente. 4. Il tempo totale di esecuzione della funzione non deve superare timeout. Se il timeout scade, tutte le richieste non completate vengono annullate e la funzione restituisce ciò che è riuscita a ottenere. 5. Usa il contesto per l'annullamento.
sobes.tech AI
Risposta dell'AI
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) // semaforo para limitare el paralelismo
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // reservamos un espacio
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // liberamos el espacio
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
}