直接回答:weak.Pointer[T] 是不阻止 GC 回收的引用:通过它持有的对象仍可被回收,回收后 weak 引用自动变 nil。典型场景是规范化(canonicalization)缓存——比如 interning 字符串/字节切片,希望“有人用就复用同一份,没人用就释放”,用普通 map 持有会把所有键值永久钉在内存里,弱引用让缓存条目随使用方消亡而自动清理。
展开解析:之前这类需求只能用 finalizer 加指针擦除的 hack(利用 SetFinalizer 在回收时从 map 删除条目),脆弱且要两轮 GC。weak 包提供了一等支持:weak.Make 创建、Value() 返回强引用或 nil,配合 cleanup 可以做精确的资源释放通知。经典用例:唯一化映射(map[string]weak.Pointer[T] 的实现、符号表)、大对象的可丢弃缓存(图片解码结果,内存紧张时允许 GC 收走,下次重新生成)、避免监听器模式的泄漏。使用注意:Value() 返回后必须立即使用并持有,两次调用间对象可能已被回收;弱引用对象间的引用图有约束(弱引用指向的对象不能反过来经由强引用链构成环依赖语义问题);与 sync.Pool 的区别是 Pool 无键且随时清空,weak 提供按键的稳定复用。它和 unique 包(1.23 的字符串规范化)是同一波内存治理能力,体现 Go 对长生命周期服务内存压力的关注。
追问方向:弱引用与 finalizer 的清理时序有何差别?interning 的收益怎么量化?
(约 470 字)