Golang 面試題(3) 兩個協程輪流打印字母和數字

Golang面試編程題3

實現兩個協程輪流輸出A 1 B 2 C 3 .... Z 26

方案1:有緩衝的chan


func ChannelFunc() {
	// 思想:兩個g,一個輸出數字,一個輸出字母,重點是如何控制兩個g的打印順序,讓其可以輪流打印

	// 分別使用兩個緩存爲1的chan,來控制兩個g的打印順序
	strChan := make(chan int, 1)
	numChan := make(chan int, 1)

	strChan <- 0 // 先往字符chan中塞入,此時strChan再塞入會堵塞

	// 負責打印字母
	go func() {
		for i := 65; i <= 90; i++ {
			<-strChan // strChan取出,因爲之前先塞入了,所以此處不會堵塞,會直接打印字符A..Z
			fmt.Printf("%v ", string(rune(i))) // 打印字母
			numChan <- i // numChan 塞入,塞入後,另一個g的numChan取出操作才能進行
		}
		return
	}()

  // 負責打印數字
	go func() {
		for i := 1; i <= 26; i++ {
			<-numChan // 一直阻塞,直到字母被打印,這樣每次數字都是在字母后面被打印的
			fmt.Printf("%v ", i) /// 打印數字
			strChan <- i // strChan塞入,此處塞入後,上面協程的strChan取出操作才能進行,纔會打印字母,這樣保證了打印完數字後,緊接着打印字母
		}
		return
	}()

	time.Sleep(1 * time.Second)
	fmt.Println()
	
	// A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 16 Q 17 R 18 S 19 T 20 U 21 V 22 W 23 X 24 Y 25 Z 26 
}

方案2:無緩衝的chan

func ChannelFunc() {
	strChan := make(chan int)
	numChan:= make(chan int)

	// 打印字母
	go func() {
		for i := 65; i <= 90; i++ {
			// 保證字母先被打印
			fmt.Printf("%v ", string(rune(i)))
			strChan <- i // strChan塞入,通知數字可以被打印了
			<-numChan // numChan一直被阻塞,直到被g2通知可以打印字母了
		}
		return
	}()

	// 打印數字
	go func() {
		for i := 1; i <= 26; i++ {
			<-strChan // strChan拉取,一直被阻塞,直到被strChan被塞入,即被g1通知數字可以打印了之後才解除阻塞
			fmt.Printf("%v ", i)
			numChan <- i // numChan塞入,通知g1可以打印字母
		}
		return
	}()

	time.Sleep(1 * time.Second)
	fmt.Println()
}

總結:

  • 一個協程負責打印數字,一個協程負責打印字母,分開進行,我們只需要控制其輪流打印即可
  • 採用有無緩衝的Chan都可實現輪流控制
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章