package main import ( "fmt" "runtime" "sync" "time" ) var c int func counter() int { c++ return c } func main2() { a := 100 go func(x, y int) { time.Sleep(time.Second) println("go:", x, y) }(a, counter()) a += 100 println("main:", a, counter()) time.Sleep(time.Second * 3) } // 進程退出不會等待併發任務結束,可用通道阻塞,而後發出退出信號 func main3() { exit := make(chan struct{}) go func() { time.Sleep(time.Second) println("goroutine ....") // 除關閉通道外,寫入數據也可接觸通道 close(exit) }() println("main ....") <-exit println("main exit.") } // 等待多個併發任務結束,使用sync.WaitGroup func main4() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) // 累加計數 go func(id int) { defer wg.Done() // 遞減計數 time.Sleep(time.Second) println("goroutine", id, "done.") }(i) } println("main ...") wg.Wait() println("main exit.") } // 可在多處使用wait,它們都能接收到通知 func main5() { var wg sync.WaitGroup wg.Add(1) go func() { wg.Wait() // 等待歸零,解除阻塞 println("wait exit.") }() go func() { time.Sleep(time.Second) println("done.") wg.Done() }() wg.Wait() // 等待歸零,解除阻塞 println("main exit.") } func main7() { var wg sync.WaitGroup var gs [5]struct { id int result int } for i := 0; i < len(gs); i++ { wg.Add(1) go func(id int) { defer wg.Done() gs[id].id = id gs[id].result = (id + 1) * 100 }(i) } wg.Wait() fmt.Printf("%+v\n", gs) } // Gosched 暫停,釋放線程去執行其餘任務。當前任務被放回隊列,等待下次調度時恢復執行 func main8() { runtime.GOMAXPROCS(1) exit := make(chan struct{}) go func() { defer close(exit) go func() { println("b") }() for i := 0; i < 4; i++ { println("a:", i) if i == 1 { // 讓出當前線程,調度執行 b runtime.Gosched() } } }() <-exit } // Goexit 當即終止當前任務,運行時確保全部已註冊延遲調用被執行 // 不管身處哪一層,Goexit 都能當即終止整個調用棧,這與return僅退出當前函數不一樣 // 標準庫函數 os.Exit 可終止進程,但不會執行延遲調用 func main9() { exit := make(chan struct{}) go func() { defer close(exit) defer println("a") func() { defer func() { println("b", recover() == nil) }() func() { println("c") runtime.Goexit() // 當即終止整個調用棧 println("c done.") }() println("b done.") }() println("a done.") }() <-exit }