Middle+
Užduotis: „Lygiagretus URL apdorojimas su laiko apribojimu“ Parašykite funkciją fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, kuri: 1. Kiekvienam URL atlieka HTTP GET užklausą (galima naudoti http.Get). 2. Grąžina map[string]string, kur raktas yra URL, o reikšmė – atsakymo turinys (kaip eilutė) arba tuščia eilutė klaidos/timeout atveju. 3. Vienu metu vykdomas ne daugiau kaip maxParallel užklausų. 4. Bendra funkcijos veikimo trukmė neturi viršyti timeout. Jei laikas pasibaigia, visos nepabaigtos užklausos atšaukiamos, ir funkcija grąžina tai, ką pavyko. 5. Naudokite kontekstą atšaukimui.
sobes.tech AI
Atsakymas iš 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) // semaphore for limiting parallelism
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // reserve a slot
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // release the slot
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
}