func collectRTT(ctx context.Context, urls []string) (map[string]time.Duration, error) {

Функция collectRTT параллельно измеряет время отклика (RTT) для списка URL-адресов с помощью горутин.

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

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

Функция collectRTT параллельно измеряет время отклика (RTT) для списка URL-адресов с помощью горутин.

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

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

Условие

func collectRTT(ctx context.Context, urls []string) (map[string]time.Duration, error) { pingMap := make(map[string]time.Duration, len(urls)) var mu sync.Mutex var wg sync.WaitGroup errCh := make(chan error, 1)

for _, url := range urls {
    wg.Add(1)
    go func(u string) {
        defer wg.Done()
        dur, err := rtt(ctx, u)
        if err != nil {
            select {
            case errCh <- fmt.Errorf("failed to rtt %s, %w", u, err):
            default:
            }
            return
        }
        mu.Lock()
        pingMap[u] = dur
        mu.Unlock()
    }(url)
}

wg.Wait()
close(errCh)

if err := <-errCh; err != nil {
    return nil, err
}
return pingMap, nil

}

Ответ

Функция collectRTT параллельно измеряет время отклика (RTT) для списка URL-адресов с помощью горутин.

Основные моменты реализации:

  • Для каждого URL запускается отдельная горутина, которая вызывает функцию rtt(ctx, u).
  • Используется sync.WaitGroup для ожидания завершения всех горутин.
  • Для безопасного доступа к общему мапу pingMap применяется мьютекс mu.
  • Канал errCh с буфером 1 используется для передачи первой возникшей ошибки из любой горутины.
  • Если ошибка возникает, она отправляется в errCh, но только одна, остальные игнорируются (через select с default).
  • После ожидания всех горутин канал ошибок закрывается, и если ошибка была, функция возвращает её.

Такой подход позволяет эффективно собирать RTT для множества URL параллельно, аккуратно обрабатывая ошибки и избегая гонок данных.

Пример использования мьютекса и WaitGroup:

var mu sync.Mutex
var wg sync.WaitGroup
pingMap := make(map[string]time.Duration)

wg.Add(1)
go func() {
    defer wg.Done()
    dur := time.Millisecond * 100 // пример
    mu.Lock()
    pingMap["example.com"] = dur
    mu.Unlock()
}()

wg.Wait()

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку