1. 交替打印数字和字母12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
package main
import (
"fmt"
"sync"
)
var (
numChan = make(chan struct{})
alphaChan = make(chan struct{})
wg sync.WaitGroup
)
func printNumber() {
i := 1
for {
select {
case <-numChan:
fmt.Printf("%d", i)
i++
fmt.Printf("%d", i)
i++
alphaChan <- struct{}{}
default:
break
}
}
}
func printAlphabet() {
c := 'A'
for {
select {
case <-alphaChan:
if c > 'Z' {
fmt.Println()
wg.Done() // 所有字母打印完成后通知主goroutine退出
return
}
fmt.Printf("%c", c)
c++
fmt.Printf("%c", c)
c++
numChan <- struct{}{}
default:
break
}
}
}
func main() {
go printNumber()
wg.Add(1)
go printAlphabet()
numChan <- struct{}{} // 启动数字打印
wg.Wait()
}
2. 交替打印0~100奇数和偶数
package main
import (
"fmt"
"sync"
)
func printOdd(oddCh, evenCh chan int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case num := <-oddCh:
if num > 100 {
evenCh <- num + 1 // 通知printEven结束
return
}
fmt.Println("Odd:", num)
evenCh <- num + 1
default:
break
}
}
}
func printEven(oddCh, evenCh chan int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case num := <-evenCh:
if num > 100 {
fmt.Println("End")
return
}
fmt.Println("Even:", num)
oddCh <- num + 1
default:
break
}
}
}
func main() {
var wg sync.WaitGroup
oddCh, evenCh := make(chan int), make(chan int)
wg.Add(2)
go printOdd(oddCh, evenCh, &wg)
go printEven(oddCh, evenCh, &wg)
oddCh <- 1
wg.Wait()
close(oddCh)
close(evenCh)
}
3. 三个goroutine交替打印ABC
package main
import (
"fmt"
"sync"
)
const N = 10
func main() {
var wg sync.WaitGroup
ch1, ch2, ch3 := make(chan struct{}), make(chan struct{}), make(chan struct{})
wg.Add(3)
go func(s string) {
defer wg.Done()
for i := 0; i < N; i++ {
<-ch1
fmt.Print(s)
ch2 <- struct{}{}
}
}("A")
go func(s string) {
wg.Done()
for i := 0; i < N; i++ {
<-ch2
fmt.Print(s)
ch3 <- struct{}{}
}
}("B")
go func(s string) {
wg.Done()
for i := 0; i < N; i++ {
<-ch3
fmt.Print(s)
ch1 <- struct{}{}
}
}("C")
ch1 <- struct{}{}
wg.Wait()
}
4. N个goroutine交替打印0~100
package main
import (
"fmt"
"sync"
)
const N = 10
func main() {
var wg sync.WaitGroup
chQueue := make([]chan int, N)
for i := 0; i < N; i++ {
chQueue[i] = make(chan int)
}
for i := 0; i < N; i++ {
wg.Add(1)
go func(id int, curCh, nextCh chan int) {
defer wg.Done()
for {
num, ok := <-curCh
if !ok || num > 100 {
if id != N-1 { // 如果不是最后一个goroutine,将结束数字发送到下个channel
nextCh <- num
}
return
}
fmt.Printf("第%d个协程打印的数字%d\n", id, num)
nextCh <- num + 1
}
}(i, chQueue[i], chQueue[(i+1)%N])
}
chQueue[0] <- 1
wg.Wait()
}
在使用channel时需要注意避免死锁,这通常发生在以下情况:
- 向一个没有接收者的无缓冲channel发送数据。
- 从一个没有发送者的channel接收数据。
- 缓冲channel满了之后继续发送数据,且没有接收者。
- 缓冲channel空了之后继续接收数据,且没有发送者。