Skip to content

练习 — goroutine · channel · select

对应知识点:goroutine · channel · select 对应文档:docs/phase-02-core/goroutine-channel-select.md 代码目录:workspace/phase-02/concurrency/

前置条件:掌握 function、struct、for 循环。


Level 1 — 基础

练习 1.1 · 启动 goroutine

workspace/phase-02/concurrency/main.go

要求

  • go func() { fmt.Println("worker started") }()
  • 主 goroutine 用 time.Sleep 等待 worker 输出(临时方案)
  • 注释说明为何 main 退出后 worker 可能来不及执行

练习 1.2 · 无缓冲 channel

要求

  • ch := make(chan string)
  • 一个 goroutine 发送 "AGV-001 telemetry"
  • main 接收并打印
  • 注释:无缓冲 channel 的同步特性

练习 1.3 · 有缓冲 channel

要求

  • ch := make(chan int, 3)
  • 连续发送 3 个值不阻塞
  • 第 4 个发送在单独 goroutine 中演示阻塞
  • main range 或接收全部值

Level 2 — 应用

练习 2.1 · 多 worker 发送

要求

  • 启动 3 个 goroutine,各模拟一台 AGV,向同一 channel 发送 {id, x, y}
  • main 接收 3 条消息并打印
  • 使用 struct 或 map 传递数据

练习 2.2 · select 多路复用

要求

  • telemetryChalertCh 两个 channel
  • 两个 goroutine 分别定时向 channel 写入
  • main 用 select 监听,打印收到的消息类型
  • 运行 5 秒后退出(用 time.After 或 context)

练习 2.3 · close 与 range

要求

  • 生产者 goroutine 发送 5 条 AGV 位置后 close(ch)
  • 消费者用 for v := range ch 读取
  • 验证 close 后不能再 send(注释或 recover 演示)

Level 3 — 综合

练习 3.1 · 生产者-消费者

workspace/phase-02/concurrency/pipeline.go

要求

  • 生产者:每 200ms 生成一条 Telemetry{DeviceID, X, Y, Battery}
  • 消费者:打印并过滤 Battery < 20 的告警
  • 使用有缓冲 channel(容量 10)
  • 运行 10 条后关闭 channel,优雅退出

练习 3.2 · select default 非阻塞

要求

  • 尝试从空 channel 读取会阻塞
  • select { case v := <-ch: ... default: ... } 实现非阻塞读
  • 模拟 WebSocket 写队列:有消息则写,无消息则跳过

练习 3.3 · 避免 goroutine 泄漏

要求

  • 编写一个「错误示例」:main 退出但 worker 永久阻塞在 channel 读
  • 修复:使用 done channel 或 context 通知 worker 退出
  • 在注释中说明泄漏检测思路(-race 与 pprof 概念即可)

Level 4 — 项目实践

练习 4.1 · AGV 数据管道

workspace/phase-02/concurrency/ 实现三阶段管道:

Generator → Processor → Printer
   (chan)      (chan)      (stdout)

要求

  • Generator:模拟 3 台 AGV,每秒产生位置数据
  • Processor:计算速度(相邻两点距离/时间),附加 Speed 字段
  • Printer:格式化输出,供 Web3D 前端消费的 JSON 行
  • 全部用 channel 连接,Ctrl+C 或 30 秒后优雅 shutdown
  • 文件拆分:generator.goprocessor.gomain.go

学习检查

  • [ ] goroutine 与 OS 线程、JS async 的本质区别?
  • [ ] 无缓冲 vs 有缓冲 channel 的使用场景?
  • [ ] 谁应该 close channel?close 后读会怎样?
  • [ ] select 与 switch 的区别?

提交方式

检查答案 — goroutine channel select 练习 X.X

学习导航

上一篇:Go Package Design · 对应知识文档 · 下一篇:Sync and Context