Одновременное получение данных с нескольких веб‑ресурсов

Используйте фиксированное число работников, общий context и mutex для карты. Для остановки активной загрузки сама функция скачивания должна принимать context.

Короткий ответ

Что ответить на собеседовании

Используйте фиксированное число работников, общий context и mutex для карты. Для остановки активной загрузки сама функция скачивания должна принимать context.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо написать функцию, которая будет загружать содержимое нескольких веб‑страниц параллельно, используя фиксированный пул воркеров.

Требования:

  • Создать workersCount воркеров (горутины).
  • Каждый воркер читает URL из канала inputUrls и скачивает страницу через функцию DownloadSiteContent.
  • Полученные результаты помещаются в общую потокобезопасную карту.
  • При получении сигнала отмены из контекста все воркеры должны корректно завершить работу.

Ответ

Используйте фиксированное число работников, общий context и mutex для карты. Для остановки активной загрузки сама функция скачивания должна принимать context.

Контракт DownloadSiteContent не задан. Ниже передаём её как download(ctx, url) (string, error); входной канал закрывает производитель. Возвращаются частичные данные и первая ошибка.

import (
    "context"
    "errors"
    "sync"
)

func DownloadAll(ctx context.Context, workersCount int,
    inputUrls <-chan string,
    download func(context.Context, string) (string, error),
) (map[string]string, error) {
    if workersCount < 1 { return nil, errors.New("workersCount must be positive") }
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    results := make(map[string]string)
    var mu sync.Mutex
    var wg sync.WaitGroup
    failures := make(chan error, 1)
    for i := 0; i < workersCount; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                if ctx.Err() != nil { return }
                select {
                case <-ctx.Done():
                    return
                case url, ok := <-inputUrls:
                    if !ok { return }
                    if ctx.Err() != nil { return }
                    body, err := download(ctx, url)
                    if err != nil {
                        select { case failures <- err: default: }
                        cancel()
                        return
                    }
                    mu.Lock()
                    results[url] = body
                    mu.Unlock()
                }
            }
        }()
    }
    wg.Wait()
    select {
    case err := <-failures:
        return results, err
    default:
        return results, ctx.Err()
    }
}

Повторные URL перезаписываются последним завершившимся результатом. Производитель тоже должен учитывать ctx, чтобы не зависнуть на отправке. Если download игнорирует отмену, внешний пул не может безопасно прервать её выполнение.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее