问题描述:

写一段代码,实现数字和字母被交替打印出来,最终效果如下:

1A2B3C4D5E6F7G8

代码段:

func main() {
	//初始化两个通道,一个等待通知执行,另一个在改执行后,通知对方执行;进行交替执行。
	letter,number := make(chan int),make(chan int)
	wait := sync.WaitGroup{}
	go printNum(letter,number)
	wait.Add(1)
	go printLetter(letter,number,&wait)
	number<-1
	//阻塞不退出,直到wait.Done()执行
	wait.Wait()
}

//打印数字
func printNum(letter chan int,number chan int)  {
	i := 1
	var n int
	for{
		select {
		case n = <-number:
			//number 信号为2,退出方法。
			if n == 2{
				return
			}
			fmt.Print(i)
			i++
			letter <- 1
		}
	}
}

//打印字母
func printLetter(letter chan int,number chan int,wait *sync.WaitGroup)  {
	i := 'A'
	for{
		select {
		case <-letter:
			if i > 'G'{
				number <- 2
				wait.Done()
				return
			}
			fmt.Print(string(i))
			i++
			number <- 1
		}
	}
}

源码解析:

channel

wait用来等待字母打印完成后退出循环。

 

知识点:

1.通道channel的创建和使用:

该例子是创建不带缓冲的通道,channel接收到值后,会阻塞等待直达信号值输出。带缓冲的通过创建例如,区别是在缓冲区满之前,不会阻塞代码往下的执行:

//带缓冲channel
ch := make(chan string, 10)

//创建只读channel
chonlyread := make(<-chan int, 10)
//创建只写channel
chonlywrite := make(chan<- int, 10)

2.select 的使用,以下描述了 select 语句的语法:

  • 每个 case 都必须是一个通信
  • 所有 channel 表达式都会被求值
  • 所有被发送的表达式都会被求值
  • 如果任意某个通信可以进行,它就执行,其他被忽略。
  • 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。
    否则:
    1. 如果有 default 子句,则执行该语句。
    2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。