题目描述
使用两个 goroutine 交替打印序列,一个 goroutine 打印数字, 另外一个 goroutine 打印字母, 最终效果如下:
1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z
思路
使用 channel 来控制打印的进度。使用两个 channel,来分别控制数字和字母的打印进度,数字打印完通过 channel 通知数字打印,数字打印完通过 channel 通知字母打印。如此周而复始,直到终止条件。
代码参考
func printEach() {
letter, number := make(chan bool), make(chan bool)
wait := sync.WaitGroup{}
go func() {
i := 1
for {
select {
case <-number:
fmt.Print(i)
i++
letter <- true
}
}
}()
wait.Add(1)
go func(wait *sync.WaitGroup) {
str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i := 0
for {
select {
case <-letter:
if i >= len(str) {
wait.Done()
return
}
fmt.Print(str[i : i+1])
i++
if i >= len(str) {
wait.Done()
return
}
number <- true
}
}
}(&wait)
// 让数字先开始打印
number <- true
// 等待循环结束,表示整个打印可以结束了
wait.Wait()
// 最后关闭 channel,防止内存泄露
close(letter)
close(number)
}
代码解释:
letter用于通知打印字母,number用于通知打印数字。sync.Waitgroup{}用于阻塞主线程等待整个打印过程结束。
倒数第 4 行中的number <- true表示让数字先开始打印。
结束后记得关闭 channel,防止内存泄露
扩展
有三个函数,分别可以打印 “cat” “dog” “fish”,要求每个函数都起一个 goroutine,并按照 “cat” “dog” “fish” 的顺序打印在屏幕上,5 次。
func printCatDogFish(){
cat, dog, fish := make(chan struct{}), make(chan struct{}), make(chan struct{})
wg := &sync.WaitGroup{}
target := 100
go func() {
// cat
for {
select {
case <-cat:
fmt.Println("cat")
dog <- struct{}{}
}
}
}()
go func() {
// dog
for {
select {
case <-dog:
fmt.Println("dog")
fish <- struct{}{}
}
}
}()
wg.Add(1)
go func(w *sync.WaitGroup) {
// fish
defer w.Done()
i := 0
for {
select {
case <-fish:
fmt.Println("fish")
i++
if i >= target {
return
}
cat <- struct{}{}
}
}
}(wg)
cat <- struct{}{}
wg.Wait()
close(cat)
close(dog)
close(fish)
}
