章节摘要:这是 Go 的主场。本章从"并发与并行的区别"讲起,覆盖 goroutine 的启动成本与调度模型(GMP)、channel 的阻塞语义与缓冲设计、select 的多路复用与超时模式、sync 包的锁族与 WaitGroup、Once、原子操作,最后用 Context 打通"取消传播"这一生产系统的命脉。读完你能写出正确且不泄漏的并发程序。
阅读完本章,你应当能够:
Don't communicate by sharing memory; share memory by communicating——别用共享内存来通信,用通信来共享内存。
go 关键字、主 goroutine 退出即程序退出、GMP 调度模型、泄漏的成因。
无缓冲的同步语义、有缓冲的异步语义、关闭与遍历、单向通道与高级模式(信号、扇入扇出、退出)。
多路复用、随机公平选择、超时与非阻塞模式、nil 通道的妙用、与 Context 联动。
数据竞争的本质、Mutex 与 RWMutex、WaitGroup、Once、Cond 与原子操作、错误用法清单。
接口构成、四种派生、取消与超时传播、Value 的克制使用、惯例与反模式。
goroutine 是"执行",channel 是"通信",select 是"通信的调度台",sync 族是"共享内存时的护栏",Context 是"跨层取消的信令网"。五者按此顺序递进,最后在"生产级并发模式"里合流。
┌────────────┐ ┌────────────┐ ┌────────────┐ │ goroutine │─▶ │ channel │─▶ │ select │ │ 谁在干活 │ │ 怎么传话 │ │ 听谁的 │ └────────────┘ └────────────┘ └─────┬──────┘ ┌────────────┐ ┌────────────┐ │ │ sync 锁族 │─▶ │ Context │◀────────┘ │ 共享护栏 │ │ 全链路取消 │ └────────────┘ └────────────┘
并发是 Go 最容易写出"看起来对、跑起来随机出错"代码的地方。学习时坚持两条纪律:第一,每个 goroutine 都用 WaitGroup 或 channel 明确"谁会等它结束";第二,用 go test -race 跑竞态检测,把数据竞争当作编译错误一样对待。建议按"顺序执行 → 并发改造 → 加超时与取消"三步完成一个爬虫小项目,逐步体会 select 与 Context 的价值。