package main

import (
	"fmt"
	"log"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup

func SayGreetings(greeting string, times int) {
	for i := 0; i < times; i++ {
		log.Println(greeting)
		d := time.Second * time.Duration(rand.Intn(5)) / 2
		time.Sleep(d)
	}
	wg.Done() // 通知当前任务已经完成。
}

func main() {
	// {
	// 	//waitgroup 样例
	// 	rand.Seed(time.Now().UnixNano())
	// 	log.SetFlags(0)
	// 	wg.Add(2) // 注册两个新任务。
	// 	go SayGreetings("hi!", 10)
	// 	go SayGreetings("hello!", 10)
	// 	wg.Wait() // 阻塞在这里，直到所有任务都已完成。
	// }
	// {
	// 	wg.Add(1)
	// 	go func() {
	// 		time.Sleep(time.Second * 2)
	// 		wg.Done()
	// 		wg.Wait() // 阻塞在此
	// 	}()
	// 	wg.Wait() // 阻塞在此
	// }
	// {
	// 	fmt.Println(runtime.NumCPU()) //最多并行执行的协程数量
	// }
	// {
	// 	defer fmt.Println("The third line.")
	// 	defer fmt.Println("The second line.")
	// 	fmt.Println("The first line.")
	// 	// first second third
	// }
	// {
	// 	defer fmt.Println("9")
	// 	fmt.Println("0")
	// 	defer fmt.Println("8")
	// 	fmt.Println("1")
	// 	if false {
	// 		defer fmt.Println("not reachable")
	// 	}
	// 	defer func() {
	// 		defer fmt.Println("7")
	// 		fmt.Println("3")
	// 		defer func() {
	// 			fmt.Println("5")
	// 			fmt.Println("6")
	// 		}()
	// 		fmt.Println("4")
	// 	}()
	// 	fmt.Println("2")
	// 	return
	// 	defer fmt.Println("not reachable")
	// }
	{
		// fmt.Println(Triple(5))
	}
	{
		//协程和延迟调用的实参的估值时刻
		//延迟调用的实参，是在此延迟调用被推入延迟调用队列时被估值的。
		//匿名函数体内的表达式是在此函数被执行的时候才被逐渐估值的，不管是普通调用还是延迟、协程调用
		// {
		// 	//defer
		// 	func() {
		// 		for i := 0; i < 3; i++ {
		// 			defer fmt.Println("a:", i)
		// 		}
		// 	}()
		// 	fmt.Println()
		// 	func() {
		// 		for i := 0; i < 3; i++ {
		// 			defer func() {
		// 				fmt.Println("b:", i)
		// 			}()
		// 		}
		// 	}()
		// 	//a:2 1 0
		// 	//b:3 3 3
		// }
		// {
		// 	//同样的估值时刻规则也适用于协程调用
		// 	var a = 123
		// 	go func(x int) {
		// 		// 形参x遮挡了外层声明的变量x
		// 		fmt.Println(x)
		// 		time.Sleep(time.Second)
		// 		fmt.Println(x, a) // 123 789
		// 		fmt.Println(x, x) // 123 123 拷贝
		// 	}(a) // 将实参a传递给形参x
		// 	a = 789
		// 	time.Sleep(2 * time.Second)
		// }
	}
	// {
	// 	x, y := 3, 4
	// 	z := func(a, b int) (c int) {
	// 		println("a*a + b*b =", a*a+b*b) // a*a + b*b = 25
	// 		return a*a + b*b
	// 	}(x, y) // 立即调用并传递两个实参。 把x,y传递给a,b
	// 	fmt.Println(z)
	// }
	{
		//恐慌、恢复
		fmt.Println("hi")
		defer func() {
			v := recover()
			fmt.Println("恐慌被恢复了", v)
		}()
		panic("恐慌")

	}
}

func Triple(n int) (r int) {
	defer func() {
		fmt.Println(r)
		r += n // 修改返回值
		fmt.Println(r)
	}()
	return n + n // <=> r = n + n; return
	// return 10 ——> r=10 ——> 进入defer r=15 ——> return 15
	//这个函数先执行完return 再执行defer内部，很神奇。
}
