Назад к вопросам
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()