Go 中 `json.NewEncoder/Decoder` 与 `json.Marshal/Unmarshal` 的区别与实践
Go 中 json.NewEncoder/Decoder
与 json.Marshal/Unmarshal
的区别与实践(HTTP 示例)
在 Go 中处理 JSON 有两种主要方式:使用 json.Marshal/Unmarshal
和使用 json.NewEncoder/Decoder
。它们都能完成 JSON 的序列化与反序列化,但使用场景和优势略有不同。
🌱 一、整体概念对比
功能 | json.Marshal / json.Unmarshal | json.NewEncoder / json.NewDecoder |
---|---|---|
输入输出 | []byte / string | io.Writer / io.Reader |
性能 | 一次性读写,适合小数据 | 流式处理,适合大数据、网络请求体 |
易用性 | 简洁直观,适合内存中的 JSON 数据 | 可处理流式数据、更适合 HTTP 读写场景 |
典型应用 | JSON API 响应构建、配置文件加载等 | HTTP 请求/响应处理、文件流读取 |
🚀 二、HTTP 示例对比
我们用两个示例分别展示:
json.NewEncoder/Decoder
:直接读写http.Request.Body
和http.ResponseWriter
json.Marshal/Unmarshal
:先读完整体,再解析和返回
🧾 公共结构体定义:
type User struct {ID int `json:"id"`Name string `json:"name"`Email string `json:"email"`
}
🧪 方法一:使用 json.NewDecoder
和 json.NewEncoder
func handlerWithEncoderDecoder(w http.ResponseWriter, r *http.Request) {var user Userif err := json.NewDecoder(r.Body).Decode(&user); err != nil {http.Error(w, "invalid json", http.StatusBadRequest)return}response := map[string]interface{}{"status": "received","user": user,}w.Header().Set("Content-Type", "application/json")if err := json.NewEncoder(w).Encode(response); err != nil {http.Error(w, "encode error", http.StatusInternalServerError)}
}
🧪 方法二:使用 json.Unmarshal
和 json.Marshal
func handlerWithMarshal(w http.ResponseWriter, r *http.Request) {bodyBytes, err := io.ReadAll(r.Body)if err != nil {http.Error(w, "read error", http.StatusInternalServerError)return}var user Userif err := json.Unmarshal(bodyBytes, &user); err != nil {http.Error(w, "invalid json", http.StatusBadRequest)return}response := map[string]interface{}{"status": "received","user": user,}w.Header().Set("Content-Type", "application/json")jsonData, err := json.Marshal(response)if err != nil {http.Error(w, "encode error", http.StatusInternalServerError)return}w.Write(jsonData)
}
⚖️ 三、对比总结
对比点 | Encoder/Decoder | Marshal/Unmarshal |
---|---|---|
使用便捷性 | 可直接对接 HTTP 输入输出流 | 需要读取/写入中间变量 []byte |
适合大数据 | ✅ 是(流式处理) | ❌ 需一次性加载全部数据 |
性能优势 | 节省内存,特别适合大请求/响应 | 适合结构简单或数据量小的应用 |
调试方便 | 较复杂(不便打印中间数据) | 中间变量可供调试、日志记录 |
💡 实际建议
- 接收请求体(尤其大数据或长连接):建议使用
json.NewDecoder
- 返回响应数据(动态生成):建议使用
json.NewEncoder
- 处理缓存、小数据、临时结构体转换:使用
json.Marshal/Unmarshal
更方便
🧪 curl 测试命令
curl -X POST http://localhost:8080/encoder \-H "Content-Type: application/json" \-d '{"id": 1, "name": "Alice", "email": "alice@example.com"}'
📚 参考文档
- encoding/json 包官方文档
- Go Web 编程最佳实践
希望这篇文章能帮助你理解 json.Marshal/Unmarshal
和 json.NewEncoder/Decoder
的差异,并选择适合你项目场景的方式。