为何需要 goroutine
Go 用 轻量级协程 简化并发:栈初始几 KB,调度在用户态。后端服务高并发连接、worker pool、pipeline 都建立在 goroutine + channel 之上。
go func() {
fmt.Println("async")
}()
注意:循环里 go func 要传参,避免闭包捕获循环变量。
for i := 0; i < 3; i++ {
go func(n int) { fmt.Println(n) }(i)
}
GMP 面试答法
- G:用户态任务。
- M:内核线程,真正执行代码。
- P:本地 run queue、mcache;GOMAXPROCS 限制 P 数量。
channel 基础
ch := make(chan int) // 无缓冲
buf := make(chan int, 10) // 有缓冲,满则 send 阻塞
select 多路复用 + default 非阻塞:
select {
case v := <-ch:
fmt.Println(v)
case ch <- 1:
case <-time.After(time.Second):
}
关闭 channel
仅 发送方 应 close;多个消费者可用 for v := range ch 直到关闭。
close(ch)
v, ok := <-ch
if !ok { / drained / }
用 channel 作 信号(struct{})通知退出:
done := make(chan struct{})
go worker(done)
// ...
close(done)
常见模式
反模式
- 用 channel 当 mutex(应使用 sync.Mutex)。
- 无缓冲 + 单 goroutine 自己 send recv 死锁。
- 泄漏:goroutine 永久阻塞在 recv,无消费者。
与 Week 2 衔接
week02-go-mutex-context 讲共享内存 + 取消;channel 适合 传递所有权,mutex 适合 保护共享状态。选型口诀:用 channel 传递数据或事件,用 mutex 保护计数器/map。
结合 /chapters/computer-network 可类比:channel 像带同步的消息队列,但更轻、进程内。
实战巩固与面试表达
本篇属于 8 周冲刺 week02-go-goroutine-channel 主题。复习时先闭卷回答 frontmatter 中三张 flashcard,再展开口述两个「为什么」:为什么这种方案能 work、边界失败时如何降级。与相邻章节对照:算法篇强调复杂度与模板,Go 篇强调工程默认写法,中间件篇强调线上故障案例。
动手与自检清单
用 25 分钟限时做 1 道相关练习题或画出一张架构/数据结构示意图;用 5 分钟写 STAR 片段说明你在项目里是否用过类似技术。记录 3 个面试追问及你的标准答法,存入 /zh/notebook/master-plan 笔记。若某点不熟,回到对应 /chapters 交互 Lab 重新走一遍流程,比死记卡片更有效。
易错点提醒
避免只背名词不会画图;避免只说优点不谈 trade-off(性能、一致性、运维成本至少提一项);避免把学习 Demo 说成百万 QPS 生产。回答时使用「场景 → 方案 → 结果 → 反思」四段式,体现工程成熟度。
自检
手写:N 个 worker 求 slice 平方和;用 context 取消(下一篇)。能解释 buffered size 对吞吐与延迟的影响。