Sobes.tech
Назад к вопросам
Senior
3

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 }

Компании, где спрашивали
СБК ПАРУС

Ответ от нейросети

sobes.tech AI

Функция 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()