Middle+
Вазифа: «Параллель ишлаш URL-ларини вақт чеклови билан» Бир функция ёзинг fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, бу: 1. Ҳар бир URL учун HTTP GET сўрови амалга оширади (http.Get ишлатилиши мумкин). 2. Map[string]string қайтариб, унда калит URL, қиймати эса жавоб матни (сўз ёки сатр) ёки хато/вақт тугаши ҳолатида бўш сатр. 3. Бир вақтнинг ўзида энг кўпи maxParallel сўровлар бажарилади. 4. Функциянинг умумий ишлаш вақти timeout-дан ошмаслиги керак. Агар вақт тугаса, барча бажарилмаган сўровлар бекор қилинади ва функция эришганини қайтариб беради. 5. Бекор қилиш учун контекстдан фойдаланинг.
sobes.tech AI
Ҷавоб аз 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) // семафор для ограничения параллелизма
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // захватываем слот
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // освобождаем слот
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
}