Функция collectRTT параллельно измеряет время отклика (RTT) для списка URL-адресов с помощью горутин.
func collectRTT(ctx context.Context, urls []string) (map[string]time.Duration, error) {
Функция 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()