通过结构体嵌入 `*bytes.reader`,可直接复用其全部 `io.reader` 方法,并通过 `replace()` 动态更新底层 `[]byte`,避免手动代理方法或重复分配 reader 实例。
在 Go 中,当你需要一个可“重置”内容的 io.Reader(例如供 json.Decoder 多次解析不同数据),又不想每次新建 bytes.NewReader() 并传入新对象(导致调用方需感知生命周期),最佳实践是利用 结构体嵌入(embedding) —— 它天然支持方法提升(method promotion),让外层类型自动获得内嵌字段的所有导出方法。
以下是推荐实现:
type EZReader struct {
*bytes.Reader
}
// Replace 替换底层数据,无需重建 EZReader 实例
func (r *EZReader) Replace(data []byte) {
r.Reader = bytes.NewReader(data)
}
// Read、Seek、Len 等所有 bytes.Reader 方法均可直接调用:
// r.Read(p), r.Seek(0, io.SeekStart), r.Len()...✅ 优势说明:
⚠️ 注意事项:
? 使用示例:
r := &EZReader{bytes.NewReader([]byte(`{"name":"alice"}`))}
decoder := json.NewDecoder(r)
var u struct{ Name string }
decoder.Decode(&u) // 成功解析
r.Replace([]byte(`{"name":"bob"}`)) // 切换数据
decoder.Decode(&u) // 再次解析,无需新建 decoder这种设计兼顾了接口兼容
性、运行时效率与代码可维护性,是 Go 中处理“可变内容 Reader”场景的标准惯用法。