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

}