2025年6月

题目:一个goroutine打印0-100,一个goroutine打印a-z,两个goroutine交替打印。
考点:用channel通知另一个goroutine,并且不能出现goroutine阻塞。
核心原理:channel 是同步阻塞的
在没有缓冲的 channel(或容量已满的 channel)中:

发送方(chan <- val)会阻塞,直到有接收方准备好读取。

接收方(<-chan)也会阻塞,直到有发送方发来数据。

这种阻塞机制就可以天然地用于控制两个 goroutine 的执行顺序。

方案一:
两个channel,一个用来控制打印数字,一个用来控制打印字母,goroutine先接收channel再开始打印,如果没有接收到信号就会阻塞,打印完再作为发送方向对方的channel发送信号,并且第二个goroutine打印完就不要再向channel发送信号了,否则会死锁。因为第一个goroutine已经打印完,不会再接收channel,导致goroutine死锁。

func Printnumandstring() {
    chNumber := make(chan struct{})
    chStr := make(chan struct{})
    wg := &sync.WaitGroup{}
    wg.Add(2)

    go func() {
        defer wg.Done()
        i := 0
        for i <= 100 {
            <-chNumber
            for j := 0; j < 4 && i <= 100; j++ {
                println(i)
                i++
            }
            chStr <- struct{}{}
        }
    }()

    go func() {
        defer wg.Done()
        for i := 'a'; i <= 'z'; i++ {
            <-chStr
            println(string(i))
            if i != 'z' {
                chNumber <- struct{}{}
            }
        }
    }()

    chNumber <- struct{}{}
    wg.Wait()
}