Loading

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()
}
posted @ 2021-12-19 17:10  励码万言  阅读(188)  评论(0编辑  收藏  举报