json.Marshal 和 json.Unmarshal 慢因标准库依赖反射动态检查字段,导致高并发下CPU和内存开销大;easyjson通过代码生成绕过反射,配合结构体强约定、避免interface{}/map[string]interface{}、复用缓冲区等可显著提升性能。
json.Marshal 和 json.Unmarshal 会慢?Go 标准库的 encoding/json 包在运行时大量依赖反射(reflect),每次序列化/反序列化都要动态检查结构体字段名、标签、可导出性、嵌套关系等。这意味着:字段越多、嵌套越深、类型越杂(如 interface{}、map[string]interface{}),性能损耗越明显。尤其在高并发 API 场景下,CPU 时间常被反射和内存分配吃掉大半。
easyjson 替代标准 json 包(零反射)easyjson 是最成熟、兼容性最好的零反射 JSON 库之一。它不运行时解析结构体,而是通过代码生成器提前把 MarshalJSON / UnmarshalJSON 方法写死到源码里,彻底绕过 reflect。
go install github.com/mailru/easyjson/...@latest
easyjson -all user.go(会在同目录生成
user_easyjson.go)user.MarshalJSON() 和 eas
yjson.UnmarshalFromReader(r, &u),而非 json.Marshal
easyjson 运行时,需在项目中 import "github.com/mailru/easyjson/json"
interface{} 和 map[string]interface{} 的泛型解码这类类型强制 json 包走最通用、最慢的路径——所有键值对都转成 map[string]interface{},再逐层递归构建,同时伴随大量 interface{} 类型断言和内存分配。
*string、*int64)代替 interface{}
json.RawMessage 延迟解析:type Event struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
} 后续按 Type 分支再调用具体结构体的 UnmarshalJSON
json.Unmarshal([]byte, &map[string]interface{})
bytes.Buffer 和预分配切片减少 GC 压力频繁调用 json.Marshal 会产生大量临时 []byte,触发 GC;而 json.Encoder / json.Decoder 默认包装 io.Reader/io.Writer,底层也会反复分配缓冲区。
bytes.Buffer 并复用:var buf bytes.Buffer buf.Grow(1024) err := json.NewEncoder(&buf).Encode(obj) // 使用 buf.Bytes(),之后调用 buf.Reset()
[]byte 并传给自定义 MarshalJSON 方法json.Marshal —— 把多次序列化合并进一个 Encoder 流更省真正影响 JSON 性能的从来不是算法本身,而是反射开销、内存分配节奏和类型不确定性。生成式方案(如 easyjson)和结构体强约定,比任何运行时调优都管用。但要注意:一旦结构体变更,必须重新生成代码,CI 中漏掉这步会导致静默降级回标准包。