How to Handle Partial Failures in Concurrent Go Code

Handle partial failures in Go by checking errors per goroutine, using channels for propagation, and canceling remaining work via context.

Handle partial failures in concurrent Go code by checking errors immediately after each goroutine's work and using channels or sync.WaitGroup to coordinate completion and error propagation. Use a context.Context to cancel remaining work if a critical failure occurs, ensuring no goroutine leaks or continues processing invalid data.

package main

import (
	"context"
	"errors"
	"fmt"
	"sync"
)

func worker(ctx context.Context, id int, wg *sync.WaitGroup, errCh chan<- error) {
	defer wg.Done()
	if ctx.Err() != nil {
		return
	}
	// Simulate work that might fail
	if id == 3 {
		errCh <- errors.New("worker 3 failed")
		return
	}
	fmt.Printf("Worker %d done\n", id)
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	var wg sync.WaitGroup
	errCh := make(chan error, 5)

	for i := 1; i <= 5; i++ {
		wg.Add(1)
		go worker(ctx, i, &wg, errCh)
	}

	go func() {
		wg.Wait()
		close(errCh)
	}()

	for err := range errCh {
		if err != nil {
			fmt.Println("Partial failure detected:", err)
			cancel() // Stop remaining workers
			break
		}
	}
}