func Do(ctx context.Context, users []User) (map[string]int64, error) { var mu sync.Mutex var wg sync.WaitGroup ch := make(chan error, len(users)) names := make(map[string]int64, 0) ctxWithCancel, cancel := context.WithCancel(ctx) wg.Add(len(users)) for _, u := range users { go func() { defer wg.Done() select { case name, err := fetch(ctx, u): if err != nil { ch <- err return } mu.Lock() names[name] = names[name] + 1 mu.Unlock() case <-ctxWithCancel.Err: } }() } return names, nil }
sobes.tech AI
Answer from AI
The provided code has several issues:
-
Inside the
for _, u := range usersloop, a goroutine is launched, but the variableuis not passed into the closure, which can lead to data races and incorrect behavior. -
In the
selectstatement,case name, err := fetch(ctx, u):is used, but this syntax is invalid inselect—selectworks with channels, not functions. -
The error channel
chis filled, but never read from, which can cause blocking. -
The context
ctxWithCancelis created, butcancel()is not called, which can lead to leaks. -
The function returns
namesandnilimmediately, without waiting for goroutines to finish.
Corrected example:
func Do(ctx context.Context, users []User) (map[string]int64, error) {
var mu sync.Mutex
var wg sync.WaitGroup
ch := make(chan error, len(users))
names := make(map[string]int64)
ctxWithCancel, cancel := context.WithCancel(ctx)
defer cancel()
wg.Add(len(users))
for _, u := range users {
u := u // local copy for closure
go func() {
defer wg.Done()
name, err := fetch(ctxWithCancel, u)
if err != nil {
ch <- err
cancel() // cancel remaining operations
return
}
mu.Lock()
names[name]++
mu.Unlock()
}()
}
wg.Wait()
close(ch)
for err := range ch {
if err != nil {
return nil, err
}
}
return names, nil
}
Main changes:
- Created a local copy
ufor each goroutine. - Removed
selectwith function call;fetchis called directly. - Added
cancel()call upon error. - Added waiting for all goroutines to finish with
wg.Wait(). - Errors are collected from the channel and returned.
This ensures correct parallel processing and proper management of context and errors.