来自 #139 的架构级评审建议。不阻塞合入,仅供参考是否有更好的架构解法。
💡 [建议 · 内存] DecodeScanRequest 返回的切片指向入参底层数组 pkg/proto/scan.go:65
问题根因:DecodeScanRequest 返回的 ScanRequest.Start 和 .End 是直接对入参 data 的切片(data[off : off+startLen]),没有拷贝。如果调用方在解码后修改或复用 data 底层数组,这些切片的内容将被污染。当前调用方 handleScan 在路由中解码后立即使用,不存在此问题,但这是一个脆弱的约定——如果未来引入异步处理或请求排队,就会触发 use-after-free 类问题。
为什么低级解法不够:加注释要求调用方不要复用 data 是常见的低级解法,但易被忽略。逐个拷贝会额外分配。
架构级方案:在包文档层面确立解码函数的所有权约定:Decode* 返回的 []byte 字段是否共享入参内存。对于 SCAN 这种一次性使用的请求,不拷贝是合理的零拷贝设计;但应明确文档化,并在关键点加注释。或者采用双 API 模式:DecodeScanRequest(零拷贝,快速)和 DecodeScanRequestCopy(拷贝,安全),让调用方按需选择。
代价/收益:当前设计零拷贝带来了 wire→decode 路径的最低延迟,对边缘设备有利;代价是调用方需感知所有权约定。建议当前 PR 中保持零拷贝,加包级注释说明即可。
💡 [建议 · 内存] DecodeScanRequest 返回的切片指向入参底层数组
pkg/proto/scan.go:65问题根因:
DecodeScanRequest返回的ScanRequest.Start和.End是直接对入参data的切片(data[off : off+startLen]),没有拷贝。如果调用方在解码后修改或复用data底层数组,这些切片的内容将被污染。当前调用方handleScan在路由中解码后立即使用,不存在此问题,但这是一个脆弱的约定——如果未来引入异步处理或请求排队,就会触发 use-after-free 类问题。为什么低级解法不够:加注释要求调用方不要复用 data 是常见的低级解法,但易被忽略。逐个拷贝会额外分配。
架构级方案:在包文档层面确立解码函数的所有权约定:
Decode*返回的[]byte字段是否共享入参内存。对于 SCAN 这种一次性使用的请求,不拷贝是合理的零拷贝设计;但应明确文档化,并在关键点加注释。或者采用双 API 模式:DecodeScanRequest(零拷贝,快速)和DecodeScanRequestCopy(拷贝,安全),让调用方按需选择。代价/收益:当前设计零拷贝带来了 wire→decode 路径的最低延迟,对边缘设备有利;代价是调用方需感知所有权约定。建议当前 PR 中保持零拷贝,加包级注释说明即可。