Sobes.tech
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

}