Go

How do you collect all errors from concurrent workers rather than just the first?

Question 314MediumGo 1.22 to 1.25

Give each worker its own slot in a pre-sized slice. Each goroutine writes a different element, so there is no data race and no mutex. Then call errors.Join, which skips nil entries and returns nil if every slot is nil.

func RunAll(jobs []func() error) error {
	errs := make([]error, len(jobs))
	var wg sync.WaitGroup
	for i, job := range jobs {
		wg.Add(1)
		go func() {
			defer wg.Done()
			if err := job(); err != nil {
				errs[i] = fmt.Errorf("job %d: %w", i, err)
			}
		}()
	}
	wg.Wait() // happens-before: all writes are visible after Wait
	return errors.Join(errs...)
}

Alternatives: a buffered channel make(chan error, len(jobs)) that you drain after Wait, or a mutex-guarded append. With an unbuffered channel, workers block unless someone is reading at the same time, a classic goroutine leak and deadlock. Close result channels only after wg.Wait(), usually from a separate goroutine, when the reader ranges over the channel.

The interviewer is checking how you reason about memory: why is writing to distinct slice indices safe while append is not?

More on Error Handling & panics

All 37 Error Handling & panics questions