Golang实战:使用 Goroutine 实现数字与字母的交叉打印
前言
在 Go 语言中,goroutine 是轻量级的并发执行单元,它使得我们能够非常方便地实现并发编程。本文将通过一个经典的案例 —— 使用两个 goroutine 交替打印数字和字母,来演示如何利用 channel 控制 goroutine 的执行顺序,并加深对 Go 并发模型的理解。
🎯 题目描述
编写一个 Go 程序,使用两个 goroutine:
一个 goroutine 打印数字 1~26;
另一个 goroutine 打印字母 ‘A’~‘Z’;
要求输出结果为:
深色版本
1 2 A 3 4 B 5 6 C … 25 26 Z
即每打印两个数字后打印一个字母,形成交错输出的效果。
🧠 解题思路
要实现两个 goroutine 按照一定顺序交替执行,关键在于控制执行流程。我们可以借助 Go 的 channel 实现同步通信机制:
使用两个 channel:numChan 和 letterChan,分别用于通知打印数字和字母;
主 goroutine 控制初始信号;
每个 goroutine 打印完相应内容后发送下一个 goroutine 的信号;
使用计数器控制循环结束。
✅ 完整代码实现
package mainimport ("fmt""time"
)func main() {numChan := make(chan struct{})letterChan := make(chan struct{})done := make(chan struct{})// 数字 goroutinego func() {for i := 1; i <= 26; i += 2 {// 等待打印两个数字的信号<-numChan// 打印两个数字fmt.Printf("%d %d ", i, i+1)// 发送打印字母的信号letterChan <- struct{}{}}close(letterChan)done <- struct{}{}}()// 字母 goroutinego func() {for ch := 'A'; ch <= 'Z'; ch++ {// 等待打印字母的信号<-letterChan// 打印一个字母fmt.Printf("%c ", ch)// 如果还没到结尾,通知继续打印下一组数字if ch != 'Z' {numChan <- struct{}{}} else {done <- struct{}{}}}}()// 启动第一个信号numChan <- struct{}{}// 等待所有任务完成<-done<-donefmt.Println("\n程序结束")
}
🔍 运行结果示例
1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 11 12 F 13 14 G 15 16 H 17 18 I 19 20 J 21 22 K 23 24 L 25 26 Z
程序结束
🛠️ 代码解析
- Channel 的作用
numChan: 控制是否可以打印数字(初始由主 goroutine 触发);
letterChan: 控制是否可以打印字母;
done: 用于主 goroutine 等待子 goroutine 结束。 - 执行流程
主 goroutine 发送第一个信号给 numChan,启动数字打印;
数字 goroutine 打印两个数字后,发送信号给 letterChan;
字母 goroutine 收到信号后打印一个字母,并再发送信号给 numChan;
循环往复,直到全部数据打印完毕;
最终主 goroutine 接收到 done 信号,程序退出。
🧪 小技巧
在实际开发中,可以通过 time.Sleep() 模拟延迟,观察 goroutine 执行顺序;
如果希望更清晰地看到输出,可以在打印语句中加入换行或空格;
使用 sync.WaitGroup 替代 done channel 也是常见做法。
📚 扩展练习建议
使用 WaitGroup 替代 done channel;
修改题目要求为:打印一次数字后打印两次字母;
尝试使用 context.Context 控制 goroutine 的取消操作;
封装成函数,支持任意数量的交替规则;
📝 总结
通过这个小例子,我们学习了以下 Go 并发编程的核心知识点:
技术点 | 应用场景说明 |
---|---|
Goroutine | 并发执行多个任务 |
Channel | 协调 goroutine 之间的执行顺序 |
主 goroutine 等待 | 确保程序不会提前退出 |