package main

import (
	"fmt"
	"sync"
)

// section: once
var (
	once     sync.Once
	config   map[string]string
	initDone bool
)

// initConfig initializes the configuration
// This will only be called once, even if called from multiple goroutines
func initConfig() {
	fmt.Println("Initializing configuration...")
	config = make(map[string]string)
	config["database"] = "localhost:5432"
	config["cache"] = "redis:6379"
	initDone = true
	fmt.Println("Configuration initialized!")
}

// getConfig ensures config is initialized before returning it
func getConfig() map[string]string {
	// Once.Do guarantees initConfig is called exactly once
	// even if multiple goroutines call getConfig simultaneously
	once.Do(initConfig)
	return config
}

// section: once

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

	// Launch multiple goroutines that all need the config
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			cfg := getConfig()
			fmt.Printf("Goroutine %d: database=%s\n", id, cfg["database"])
		}(i)
	}

	wg.Wait()
	fmt.Println("All goroutines completed")
}

// section: main

// section: output
// Output (order will vary):
// Initializing configuration...
// Configuration initialized!
// Goroutine 3: database=localhost:5432
// Goroutine 7: database=localhost:5432
// Goroutine 0: database=localhost:5432
// Goroutine 9: database=localhost:5432
// Goroutine 5: database=localhost:5432
// Goroutine 1: database=localhost:5432
// ...
// All goroutines completed
// section: output
