Go编程模式Pipeline
Go pipeline 是一种很有效的编程模式,学会这种编程方式,会使用程序的性能得到很大的提升,而且会让程序的结构更加合理。
学习博文:https://mp.weixin.qq.com/s/kQLAnh-frOALCDNU924zxQ
// stopGenerating 发送终止信号,关闭生产通道
func stopGenerating(mc chan string, sc chan struct{}) {
sc <- struct{}{}
close(mc)
}
// multiplex 多路复用 对生成者进行汇总
func multiplex(mcs ...chan string) (chan string, *sync.WaitGroup) {
mmc := make(chan string)
wg := &sync.WaitGroup{}
// 创建多个协程 遍历mms通道集合 将每个生产通道获得内容都放入mmc通道
for _, mc := range mcs {
wg.Add(1)
go func(mc chan string, wg *sync.WaitGroup) {
defer wg.Done()
for m := range mc {
mmc <- m
}
}(mc, wg)
}
return mmc, wg
}
// TestPipLineFanIn 流水线 扇入
func TestPipLineFanIn(t *testing.T) {
// 创建生产者
mc1, sc1 := generate("message from generator 1", 200*time.Millisecond)
mc2, sc2 := generate("message from generator 2", 300*time.Millisecond)
mmc, wg1 := multiplex(mc1, mc2)
// 接收ctrl+c中断信号
errs := make(chan error)
go func() {
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
errs <- fmt.Errorf("%s signal received", <-sc)
}()
// 起一个协程不断接收mmc通道内容并打印
wg2 := &sync.WaitGroup{}
wg2.Add(1)
go func() {
defer wg2.Done()
for m := range mmc {
fmt.Println(m)
}
}()
// 阻塞直到接收到退出信号
if err := <-errs; err != nil {
fmt.Println(err.Error())
}
// 调用关闭生产者方法
stopGenerating(mc1, sc1)
stopGenerating(mc2, sc2)
// 等待所有的生产者结束
wg1.Wait()
// 关闭消息汇总通道
close(mmc)
// 等待mmc打印协程结束
wg2.Wait()
}