Concurrency in Go: Using a channel to append to slices

Paul Yeo
Nov 18, 2020
type Result struct {
Item item
Error error
}
ch := make(chan Result)var wg sync.WaitGroupfor _, i:= range items { go func(i Item) {
defer wg.Done()

res, err := processItem(i)
if err != nil {
ch <- Result{Item: i, Error: err}
return
}
ch <- Result{Item: res, Error: err}
}(i)
}
go func() {
wg.Wait()
close(ch)
}
var successful, failed []Itemfor r := range ch {
if r.Error != nil {
failed = append(failed, r.Item)
return
}
succeeded = append(succeeded, r.Item)
}

Asynchronously wg.Wait(), so that the channel values are processed and appended to appropriate slices without waiting for all workers to finish.

go func() {
wg.Wait()
...
}
// vswg.Wait()

Close the channel after the workers are finished. Iterating over the channel values will terminate when the channel is closed. Close() will close after the last sent value is received and will not flush the contents.

go func() {
...
close(ch)
}
for r := range ch {
...
}
// vsfor r := range ch {
...
}
close(ch)

--

--