How to Implement Supervisor Trees in Go

Implement supervisor trees in Go by using goroutines, channels, and context to monitor and restart child processes.

Go has no built-in supervisor tree; you must implement one using goroutines, channels, and context to manage child lifecycles. Create a parent goroutine that spawns children, monitors their exit channels, and restarts them if they crash.

package main

import (
	"context"
	"fmt"
	"time"
)

func worker(ctx context.Context, id int, done chan<- int) {
	for {
		select {
		case <-ctx.Done():
			return
		default:
			fmt.Printf("Worker %d running\n", id)
			time.Sleep(2 * time.Second)
		}
	}
}

func supervisor(ctx context.Context, id int, restarts chan<- int) {
	for {
		childDone := make(chan int, 1)
		childCtx, cancel := context.WithCancel(ctx)
		go worker(childCtx, id, childDone)
		<-childDone
		cancel()
		restarts <- id
		if ctx.Err() != nil {
			return
		}
	}
}

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

	restarts := make(chan int, 10)
	go supervisor(ctx, 1, restarts)

	time.Sleep(10 * time.Second)
	for i := 0; i < 5; i++ {
		fmt.Println("Restarted:", <-restarts)
	}
}