Создайте фиксированное число работников, канал заданий и канал результатов. Ограниченный пул не допускает горутину на каждый URL и учитывает отмену.
Напишите код с worker pool для обработки слайса URL-адресов с параллельными HTTP-запросами.
Создайте фиксированное число работников, канал заданий и канал результатов. Ограниченный пул не допускает горутину на каждый URL и учитывает отмену.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Создайте фиксированное число работников, канал заданий и канал результатов. Ограниченный пул не допускает горутину на каждый URL и учитывает отмену.
Функция на Go возвращает результаты в порядке завершения; нужны импорты context, fmt, net/http, sync и time.
type URLResult struct { URL string; Status int; Err error }
func fetchURLs(ctx context.Context, urls []string, workers int) ([]URLResult, error) {
if workers < 1 { return nil, fmt.Errorf("workers must be positive") }
client := &http.Client{Timeout: 5 * time.Second}
jobs := make(chan string)
results := make(chan URLResult)
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for url := range jobs {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
r := URLResult{URL: url, Err: err}
if err == nil {
resp, err := client.Do(req)
r.Err = err
if err == nil {
r.Status = resp.StatusCode
resp.Body.Close()
}
}
results <- r
}
}()
}
go func() {
defer close(jobs)
for _, url := range urls {
select {
case jobs <- url:
case <-ctx.Done(): return
}
}
}()
go func() { wg.Wait(); close(results) }()
var all []URLResult
for r := range results { all = append(all, r) }
return all, ctx.Err()
}
Основная функция всегда вычитывает results до закрытия, поэтому отправители не остаются заблокированными. HTTP-коды 4xx/5xx доступны в Status и оцениваются отдельно. При отмене результат может быть частичным.