Одновременная проверка большого списка доменов с ограничением количества запросов

Создайте 100 работников и сохраняйте результат каждой проверки по её индексу. После Wait можно вывести плохие домены в исходном порядке.

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

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

Создайте 100 работников и сохраняйте результат каждой проверки по её индексу. После Wait можно вывести плохие домены в исходном порядке.

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

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

Условие

Необходимо изменить существующий пример так, чтобы проверка 1000 доменов (функция checkDomain) происходила параллельно, но при этом число одновременно запущенных запросов было ограничено (например, не более 100). После завершения проверки следует вывести все домены, для которых checkDomain вернула false – то есть «плохие» домены.

import 
        "fmt"

func main () {
    for _, val := range getData() {
        if !checkDomain(val) {
            fmt.Printf("%s is bad \n", val)
        }
    }
}

func getData () []string{
    return [] string("1.test", "2.test", /.../ "1000.test")
}
func checkDomain(host string) bool {
    return true
} 

Требуется добавить механизм ограничения количества одновременно работающих горутин (или аналогичный подход), собрать результаты проверок и вывести только те домены, которые не прошли проверку.

Ответ

Создайте 100 работников и сохраняйте результат каждой проверки по её индексу. После Wait можно вывести плохие домены в исходном порядке.

getData в условии содержит псевдокод: реальный срез записывается через []string{...}. Решение принимает уже подготовленные данные и функцию проверки.

import (
    "fmt"
    "sync"
)

func PrintBad(domains []string, checkDomain func(string) bool) {
    bad := make([]bool, len(domains))
    jobs := make(chan int)
    var wg sync.WaitGroup
    for worker := 0; worker < 100; worker++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for i := range jobs {
                bad[i] = !checkDomain(domains[i])
            }
        }()
    }
    for i := range domains { jobs <- i }
    close(jobs)
    wg.Wait()
    for i, failed := range bad {
        if failed { fmt.Printf("%s is bad\n", domains[i]) }
    }
}

Разные работники пишут разные элементы фиксированного среза, чтение начинается после Wait. checkDomain должна быть потокобезопасной и иметь сетевой таймаут: этот контракт без context не позволяет прервать зависший запрос снаружи.

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

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

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

Подробнее