Senior
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
Answer from AI
The collectRTT function concurrently measures the response time (RTT) for a list of URLs using goroutines.
Key implementation points:
- A separate goroutine is launched for each URL, which calls the
rtt(ctx, u)function. sync.WaitGroupis used to wait for all goroutines to finish.- A mutex
muis used for safe access to the shared mappingMap. - A buffered channel
errChwith capacity 1 is used to pass the first error encountered from any goroutine. - If an error occurs, it is sent to
errCh, but only one error is sent; others are ignored (viaselectwithdefault). - After waiting for all goroutines, the error channel is closed, and if an error was received, the function returns it.
This approach allows efficient collection of RTTs for multiple URLs in parallel, handling errors gracefully and avoiding data races.
Example of using mutex and 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 // example
mu.Lock()
pingMap["example.com"] = dur
mu.Unlock()
}()
wg.Wait()