package main

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

func say(s string, id int) {
	for i := 0; i < 3; i++ {
		fmt.Printf("[%d] %s: step %d\n", id, s, i)
		time.Sleep(100 * time.Millisecond) // 模拟工作
	}
}

func main() {
	fmt.Println("=== 1. 单线程顺序执行 ===")
	say("Hello", 1)
	say("World", 2)

	fmt.Println("\n=== 2. 使用 Goroutine 并发执行 ===")
	go say("Goroutine-A", 1)
	go say("Goroutine-B", 2)

	// 主 goroutine 等待 1 秒，否则程序会提前退出
	time.Sleep(1 * time.Second)

	fmt.Println("\n=== 3. 使用 sync.WaitGroup 安全等待 ===")
	var wg sync.WaitGroup

	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			fmt.Printf("Worker %d started\n", id)
			time.Sleep(time.Duration(id*200) * time.Millisecond)
			fmt.Printf("Worker %d finished\n", id)
		}(i)
	}

	wg.Wait() // 阻塞直到所有 goroutine 完成
	fmt.Println("All workers done!")

	fmt.Println("\n=== 4. 查看当前 GOMAXPROCS 和 CPU 核心数 ===")
	fmt.Printf("CPU 核心数: %d\n", runtime.NumCPU())
	fmt.Printf("GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0)) // 0 表示不修改，仅查询

	fmt.Println("\n=== 5. 手动设置 GOMAXPROCS（通常不需要）===")
	old := runtime.GOMAXPROCS(2)
	fmt.Printf("旧 GOMAXPROCS: %d, 新设为: 2\n", old)
	runtime.GOMAXPROCS(old) // 恢复原值

	fmt.Println("\n=== 6. 观察 Goroutine 数量变化 ===")
	fmt.Printf("启动前 Goroutine 数: %d\n", runtime.NumGoroutine())

	var wg2 sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg2.Add(1)
		go func(n int) {
			defer wg2.Done()
			time.Sleep(200 * time.Millisecond)
		}(i)
	}

	time.Sleep(50 * time.Millisecond) // 让 goroutine 启动
	fmt.Printf("启动后 Goroutine 数: %d\n", runtime.NumGoroutine())

	wg2.Wait()
	fmt.Printf("全部完成后 Goroutine 数: %d\n", runtime.NumGoroutine())

	// 在程序最后添加
	time.Sleep(1 * time.Second)
	fmt.Printf("延迟后 Goroutine 数: %d\n", runtime.NumGoroutine())

}
