Go 中用协程交替打印的最好解决方法

(1)用协程交替打印 ABC 一百次;
(2)用协程交替打印数字,0 到 100。

我们可以利用 Channel 的阻塞机制来进行信号传递,因为无缓冲的 Channel 中,如果没有数据传入管道,那么该协程就会被阻塞直到有数据被输入进管道。

问题一:打印 ABC

设计这样一个函数:参数一接收要打印的字母,参数二为 Channel 接收上一个协程传递的信息,参数三也为 Channel 负责给下一个协程传递发送信息,参数四为 sync.WaitGroup 确保线程能够执行完。

此外,这里需要注意的是,我们每个协程完成打印任务的时候就把 Channel 关闭,因此循环到打印 C 的线程时,ChanA 已经被关闭了,此时仍向它发送数据就会报错,所以要通过 recover 方法将异常捕获。

package main

import (
	"fmt"
	"sync"
)

func printABC(letter string, ch chan struct{}, nxtch chan struct{}, wg *sync.WaitGroup) {
	defer func() {
		wg.Done()    // 宣布协程完成任务
		close(ch)    // 关闭 channel
		if r := recover(); r != nil {   //捕获异常
			fmt.Printf("\n")
		}
	}()

	for i := 0; i < 3; i++ {
		<-ch  // 接收信号并消费
		fmt.Print(letter)
		nxtch <- struct{}{}     // 发送信号给下个协程
	}
}

func main() {
	var wg sync.WaitGroup

	chA := make(chan struct{})
	chB := make(chan struct{})
	chC := make(chan struct{})

	wg.Add(3)
	go printABC("A", chA, chB, &wg)
	go printABC("B", chB, chC, &wg)
	go printABC("C", chC, chA, &wg)

	// START
	chA <- struct{}{}
	wg.Wait()
}

问题二:打印 0 到 100

函数的设计逻辑与问题一没有什么区别,主要就是在循环要打印的内容上做了一些更改,根据第一次初始化协程传入的参数开始循环打印。

package main  
  
import (  
    "fmt"  
    "sync")  
  
func printNum(start int, ch chan struct{}, nxtch chan struct{}, wg *sync.WaitGroup) {  
    defer func() {  
       wg.Done()                      // 宣布协程完成任务  
       close(ch)                      // 关闭 channel       
       if r := recover(); r != nil {  //捕获异常  
          fmt.Printf("\n")  
       }  
    }()  
  
    for i := start; i <= 2; i += 2 {  
       <-ch // 接收信号并消费  
       fmt.Printf("%d ", i)  
       nxtch <- struct{}{}   // 发送信号给下个协程  
    }  
}  
  
func main() {  
    var wg sync.WaitGroup  
  
    chA := make(chan struct{})  
    chB := make(chan struct{})  
  
    wg.Add(2)  
    go printNum(0, chA, chB, &wg)  
    go printNum(1, chB, chA, &wg)  
  
    // START  
    chA <- struct{}{}  
    wg.Wait()  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值