package main

import (
	"fmt"
	"sync"
	"time"
)

// section: wrapper
// WaitGroup wraps sync.WaitGroup with a more ergonomic API
type WaitGroup struct {
	wg sync.WaitGroup
}

// Go launches a goroutine and automatically manages the waitgroup counter
func (w *WaitGroup) Go(fn func()) {
	w.wg.Add(1)
	go func() {
		defer w.wg.Done()
		fn()
	}()
}

// Wait blocks until all goroutines have finished
func (w *WaitGroup) Wait() {
	w.wg.Wait()
}

// section: wrapper

// section: main
func main() {
	var wg WaitGroup

	// Launch multiple goroutines with the ergonomic .Go() method
	for i := 0; i < 5; i++ {
		i := i // capture range variable
		wg.Go(func() {
			fmt.Printf("Worker %d starting\n", i)
			time.Sleep(time.Duration(i*100) * time.Millisecond)
			fmt.Printf("Worker %d finished\n", i)
		})
	}

	// Wait for all goroutines to complete
	wg.Wait()
	fmt.Println("All workers completed")
}

// section: main

// section: output
/*
Sample output (order may vary with scheduler):
Worker 4 starting
Worker 0 starting
Worker 0 finished
Worker 3 starting
Worker 1 starting
Worker 2 starting
Worker 1 finished
Worker 2 finished
Worker 3 finished
Worker 4 finished
All workers completed
*/
// section: output
