Problem description
Using two goroutines to print sequences alternately, one to print numbers and the other to print letters, the result looks like this:
12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
Their thinking
Just as we learned in operating systems to control process collaboration with semaphores, we can control Goroutine collaboration with two unbuffered channels.
A channel called number notifies the Goroutine that prints the number.
Another channel, called letter, notifies the Goroutine that prints the letter.
number, letter := make(chan bool), make(chan bool)
Copy the code
The goroutine for printing a number is simple: wait for the number pipeline notification, then print the number, and finally notify the letter pipeline.
go func(a) {
i := 1
for {
<- number
fmt.Printf("%d%d", i, i + 1)
i += 2
letter <- true
}
}()
Copy the code
A goroutine that prints letters has similar contents, but controls the end condition:
go func(a) {
str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i := 0
for {
<- letter
if i >= utf8.RuneCountInString(str) {
return
}
fmt.Print(str[i : i+2])
i += 2
number <- true
}
}()
Copy the code
The complete code
Finally, we add syn.waitGroup to make the main coroutine wait for the printing coroutine to finish. The complete code looks like this:
package main
import (
"fmt"
"sync"
"unicode/utf8"
)
func main(a) {
number, letter := make(chan bool), make(chan bool)
wait := sync.WaitGroup{}
go func(a) {
i := 1
for {
<- number
fmt.Printf("%d%d", i, i + 1)
i += 2
letter <- true
}
}()
wait.Add(1)
go func(wait *sync.WaitGroup) {
str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i := 0
for {
<- letter
if i >= utf8.RuneCountInString(str) {
wait.Done()
return
}
fmt.Print(str[i : i+2])
i += 2
number <- true
}
}(&wait)
number <- true
wait.Wait()
}
Copy the code