为什么要等待子协程结束
可能是因为cpp写多了(bushi。众所周知,在cpp中,有thread.join()可以等待线程结束。但是GO中的协程没有这类API,所以就有了这个问题。主要平时写demo程序时,总是需要等待子协程结束才能完成看出来协程的调度顺序。不然就会出现下面这种情况:
1 2 3 4 5 6 7 8 9 10 11 12
| package main
import ( "fmt" )
func main(){ go sayHi(){ fmt.Println("say hello......") }() fmt.Println("main groutine....") }
|
上面程序的输出只有:
很简单,main协程跑太快了,子协程还没来得及Print,main协程就已经结束了,子协程也跟着结束了。
下面就是正文:如何让子协程顺利执行完。
通道channel
声明一个和子协程数量一致的通道数组,然后为每个子协程分配一个通道元素,在子协程执行完毕时向对应的通道发送数据;然后在主协程中,依次读取这些通道接收子协程发送的数据,只有所有通道都接收到数据才会退出主协程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package main
import "fmt"
func add(i int, j int, ch chan int) { ch <- i + j fmt.Println("add", i, j) }
func main() { chs := make([]chan int, 10) for i := 0; i < 10; i++ { chs[i] = make(chan int) go add(1, i, chs[i]) } for _, ch := range chs { <-ch }
fmt.Println("All goroutines finished") }
|
WaitGroup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import ( "fmt" "sync" )
func add_num(a, b int, done func()) { defer done() c := a + b fmt.Printf("%d + %d = %d\n", a, b, c) }
func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go add_num(i, 1, wg.Done) } wg.Wait() }
|