Подсчёт количества HTTP‑статусов при массовой проверке ссылок

Обрабатывайте URL потоком фиксированным числом работников, а HTTP-коды считайте одним агрегатором. Не размещайте миллиарды строк в памяти и не создавайте по горутине на каждую ссылку.

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

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

Обрабатывайте URL потоком фиксированным числом работников, а HTTP-коды считайте одним агрегатором. Не размещайте миллиарды строк в памяти и не создавайте по горутине на каждую ссылку.

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

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

Условие

Необходимо разработать высокоэффективный механизм обработки огромного количества URL‑адресов (порядка миллиарда). Для каждого адреса вызывается готовая функция sendRequest, которая возвращает код HTTP‑ответа. После того как все запросы выполнены, нужно вывести в стандартный вывод статистику: для каждого полученного кода вывести строку вида <КОД>: <КОЛИЧЕСТВО>. Реализовывать саму отправку запросов не требуется – её логика уже скрыта в функции sendRequest.

func main() {
    links := make([]string, 10000000000) // тут ссылки
}

func sendRequest(url string) (code int) {
    // тут ничего реализовывать не надо
}

Ответ

Обрабатывайте URL потоком фиксированным числом работников, а HTTP-коды считайте одним агрегатором. Не размещайте миллиарды строк в памяти и не создавайте по горутине на каждую ссылку.

Вместо огромного make передавайте канал, заполняемый чтением файла или БД. Нужны fmt, sort, sync; sendRequest остаётся заданной функцией:

func countCodes(links <-chan string, workers int) {
    if workers < 1 { panic("invalid workers") }
    codes := make(chan int, workers)
    var wg sync.WaitGroup
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for url := range links { codes <- sendRequest(url) }
        }()
    }
    go func() { wg.Wait(); close(codes) }()
    counts := make(map[int]uint64)
    for code := range codes { counts[code]++ }
    keys := make([]int, 0, len(counts))
    for code := range counts { keys = append(keys, code) }
    sort.Ints(keys)
    for _, code := range keys { fmt.Printf("%d: %d\n", code, counts[code]) }
}

Производитель обязан закрыть links, а sendRequest — ограничивать время работы. В исходнике 10 млрд элементов, не 1 млрд. Для такого масштаба дополнительно нужны ограничения по целевому хосту, сохранение прогресса и бюджет трафика; пример ничего не отправляет сам до вызова.

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

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

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

Подробнее