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

}