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

}}