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
:先读完整体,再解析和返回
🧾 公共结构体定义:
go
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
🧪 方法一:使用 json.NewDecoder
和 json.NewEncoder
go
func handlerWithEncoderDecoder(w http.ResponseWriter, r *http.Request) {
var user User
if 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
go
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 User
if 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 测试命令
bash
curl -X POST http://localhost:8080/encoder \
-H "Content-Type: application/json" \
-d '{"id": 1, "name": "Alice", "email": "[email protected]"}'
📚 参考文档
希望这篇文章能帮助你理解 json.Marshal/Unmarshal
和 json.NewEncoder/Decoder
的差异,并选择适合你项目场景的方式。