Middle+
Sarcină: „Procesarea paralelă a URL-urilor cu limitare de timp” Scrieți o funcție fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, care: 1. Pentru fiecare URL face o solicitare HTTP GET (se poate folosi http.Get). 2. Returnează un map[string]string, unde cheia este URL-ul, iar valoarea este corpul răspunsului (ca șir) sau un șir gol în caz de eroare/timp expirat. 3. Nu se execută mai mult de maxParallel solicitări simultan. 4. Timpul total de funcționare nu trebuie să depășească timeout. Dacă timpul expiră, toate solicitările nefinalizate sunt anulate, iar funcția returnează ceea ce a reușit. 5. Folosiți contextul pentru anulare.
sobes.tech AI
Răspuns de la 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) // semáforo para limitar o paralelismo
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // reservar um espaço
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // liberar o espaço
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
}