该用 goroutine 而非系统线程时:需高并发处理大量 I/O 等待任务(如 HTTP 请求、数据库查询)或成千上万活跃连接;避免用于 CPU 密集型循环或需串行执行的共享状态更新。
什么时候该用 goroutine 而不是系统线程
Go 的并发模型核心是轻量级的 goroutine,它不是对 OS 线程的简单封装,而是在用户态由 Go 运行时调度的协程。当你需要同时处理成百上千甚至上万的活跃连接(比如 HTTP 服务、消息代理、实时推送),或执行大量 I/O 等待任务(如数据库查询、RPC 调用、文件读写)时,goroutine 比直接创建系统线程更合适。
常见误用场景包括:在 CPU 密集型循环里无节制启动 goroutine(比如暴力遍历计算),这不会提升性能,反而因调度开销和内存占用拖慢整体速度;或者把本该串行的逻辑(如共享状态更新)强行并发,引发竞态。
- 适合:
http.Server每个请求启一个goroutine、长连接心跳管理、批量调用第三方 API 并聚合结果 - 不适合:
for i := 0; i (应改用 worker pool + channel 控制并发数) - 关键判断点:任务是否常被 I/O 或 channel 操作阻塞?阻塞时能否让出执行权给其他
goroutine?
channel 传值还是传指针?为什么 select 容易卡死
向 channel 发送数据会拷贝值。如果结构体较大(比如含 []byte 或嵌套 map),传值开销明显;但若只传指针,需确保接收方不意外修改原始数据,或在 goroutine 生命周期外访问已释放内存。
select 卡死通常是因为所有 case 对应的 channel 都不可读/不可写,且没写 default 分支——此时当前 goroutine 会永久阻塞。这不是 bug,而是设计行为。