标准答案
- 返回局部变量地址、存入接口、闭包捕获和某些动态结构可能导致逃逸。
- 可通过编译器的 escape analysis 输出查看原因,而不是根据源码直觉猜测。
- 堆分配是否是瓶颈要用 benchmark、allocs/op、CPU 和 GC 指标证明。
- 减少不必要对象和复用大 buffer 有帮助,但过度复用可能造成数据竞争和生命周期错误。
题目解析
编译器会根据引用是否逃出当前作用域决定分配策略,返回局部地址、闭包捕获、接口和动态结构都可能影响逃逸,但取地址并不在所有情况下必然堆分配。
可通过编译器 escape analysis 输出、benchmark 和 allocs/op 查看结果。优化要结合 GC CPU、P99、代码可读性和目标 Go 版本,不能只追求零分配。
全局可变 buffer 可能减少分配,却会引入数据竞争、请求串数据和生命周期错误。优先消除无界对象和不必要复制,再考虑池化并明确所有权。
常见误区
- 误区:认为取地址一定导致堆分配。改正:以编译器分析和 benchmark 为准,不靠单一语法推断。
- 误区:为零分配使用全局可变 buffer。改正:使用受控池和明确所有权,防止并发数据污染。
- 误区:只看 allocs/op。改正:同时看 GC、CPU、P99、可读性和并发安全。