直接回答:sync.Pool 是每 P(processor)本地缓存的对象池:Get 先查本 P 私有区再查共享区再偷别 P 的,Put 放回本地——绝大多数操作无锁。代价是对象随时被 GC 清空(每轮 GC 清 victim),所以它只存“可丢弃的临时对象”:buffer、临时结构体,不能存连接、会话这类有状态资源。

展开解析:适合的场景画像:高频创建销毁、构造有成本、生命周期严格限定在一次请求/操作内——bytes.Buffer(encoding/json 内部就这么用)、序列化临时对象、压缩器。用了更差的场景:低频路径(池命中率低还加复杂度);对象构造本身极廉价(零值 struct 逃逸分析已优化好,池化反而阻碍);把 Pool 当连接池(无健康检查、无生命周期管理,用专用 pool);对象大小差异巨大(大 buffer 被小请求借走浪费,分级池才解)。正确用法要点:Put 前重置对象状态(清零 buffer、清 map——否则脏数据串请求,高危 bug);New 字段提供兜底构造;别对 Get 结果的容量做假设。性能验证必须做:benchmark 对比池化前后 allocs/op 与耗时,GC 压力小的服务池化收益可能为零。已知冷知识:1.20 后 GC 对 Pool 的清理粒度优化过,短生命周期对象存活率提升;池化对象若逃逸到多个 goroutine 共享,竞态自负——Pool 不保证独占语义的传递。结论:Pool 是“GC 压力下的减分配手段”,不是通用性能银弹,先 profile 后上池。

追问方向:为什么 GC 要清空 Pool?分级 buffer 池如何实现?

(约 460 字)