并发
Goroutine
go f() 启动 goroutine,由运行时调度到 OS 线程上(M:N 模型)。创建成本远低于线程,但仍非免费;海量 goroutine 应注意栈与调度开销。
Channel
chan T:未缓冲同步握手;带容量为缓冲通道。
go
ch := make(chan int, 2)
ch <- 1
v := <-ch
close(ch)
- 向 已关闭 通道发送 → panic。
- 从已关闭通道读:立即得到零值,
ok为false(v, ok := <-ch)。 - 仅发送方应
close;重复 close panic。 nil通道上收发永久阻塞,可用于select禁用某分支。
select
见控制流章。典型模式:超时
go
select {
case res := <-work:
use(res)
case <-time.After(time.Second):
return errors.New("timeout")
}
取消传播常用 context.Context 的 Done() 通道。
同步原语(sync)
| 类型 | 用途 |
|---|---|
Mutex / RWMutex | 互斥 / 读写锁 |
WaitGroup | 等待一组 goroutine 结束 |
Once | 保证某函数只执行一次 |
Cond | 条件变量 |
Pool | 对象池,减轻 GC;Get 返回值生命周期勿越界误用 |
sync/atomic 提供原子操作;复杂场景优先高层抽象或 channel;需要细粒度无锁时用 atomic 并注意内存序(Go 内存模型与原子文档)。
context
context.Background():根上下文。WithCancel/WithTimeout/WithDeadline:派生可取消上下文,须调用返回的cancel()(通常defer cancel())避免泄漏 timer/goroutine。WithValue:传递请求范围元数据,勿塞业务大对象或可选参数替代品。
常见陷阱
- 在 goroutine 中捕获循环变量:Go 1.22 前易错;现版本每轮独立,仍建议显式传参。
- 泄漏 goroutine:无退出条件的
for+ 阻塞发送/接收。 - 死锁:锁顺序不一致、channel 无配对等。
- 用
-race检测数据竞争:未同步的并发读写同一内存位置。
并行度
GOMAXPROCS 控制可同时执行用户级 Go 代码的最大 OS 线程数;默认约等于 CPU 核数。CPU 密集任务勿盲目增大 goroutine 数。