代码参考至 《Go语言精进之路》
例子1
package main
import (
"fmt"
"sync"
"time"
)
type signal struct{}
func worker(i int) {
fmt.Printf("worker %d :is working... \n", i)
time.Sleep(time.Duration(i) * time.Second)
fmt.Printf("worker %d :is done... \n", i)
}
func spawnGroup(f func(i int), num int, groupSignal <-chan signal) <-chan signal {
c := make(chan signal)
var wg sync.WaitGroup
for i := 0; i < num; i++ {
time.Sleep(1 * time.Second)
wg.Add(1)
go func(i int) {
<-groupSignal
fmt.Printf("worker %d :start to work...\n", i)
f(i)
wg.Done()
}(i + 1)
}
go func() {
wg.Wait()
c <- signal{}
}()
return c
}
func main() {
println("start a")
groupSignal := make(chan signal)
c := spawnGroup(worker, 5, groupSignal)
time.Sleep(5 * time.Second)
close(groupSignal)
<-c
println("done")
}
输出
start a
worker 3 :start to work...
worker 3 :is working...
worker 1 :start to work...
worker 1 :is working...
worker 5 :start to work...
worker 5 :is working...
worker 2 :start to work...
worker 2 :is working...
worker 4 :start to work...
worker 4 :is working...
worker 1 :is done...
worker 2 :is done...
worker 3 :is done...
worker 4 :is done...
worker 5 :is done...
done
例子2
package main
import (
"fmt"
"sync"
"time"
)
type signal struct{}
func worker(i int) {
fmt.Printf("worker %d :is working... \n", i)
time.Sleep(time.Duration(i) * time.Second)
fmt.Printf("worker %d :is done... \n", i)
}
func spawnGroup(f func(i int), num int, groupSignal <-chan signal) <-chan signal {
c := make(chan signal)
var wg sync.WaitGroup
for i := 0; i < num; i++ {
time.Sleep(1 * time.Second)
wg.Add(1)
go func(i int) {
// <-groupSignal
fmt.Printf("worker %d :start to work...\n", i)
f(i)
wg.Done()
}(i + 1)
}
go func() {
wg.Wait()
c <- signal{}
}()
return c
}
func main() {
println("start a")
groupSignal := make(chan signal)
c := spawnGroup(worker, 5, groupSignal)
time.Sleep(5 * time.Second)
// close(groupSignal)
<-c
println("done")
}
输出
start a
worker 1 :start to work...
worker 1 :is working...
worker 1 :is done...
worker 2 :start to work...
worker 2 :is working...
worker 3 :start to work...
worker 3 :is working...
worker 2 :is done...
worker 4 :start to work...
worker 4 :is working...
worker 5 :start to work...
worker 5 :is working...
worker 3 :is done...
worker 4 :is done...
worker 5 :is done...
done
前者的goruntime在启动后会堵塞在名为groupSignal的无缓存的channel上,等main goroutine通过close(groupSignal)后,所有goroutine会同时启动运行,关闭一个无缓存channel会让所有堵塞在该channel上的接收操作返回,实现一种一对多的广播机制,而后者在启动goruntime后就立即执行相应的流程,适用一般的流程中