Go 中 `json.NewEncoder/Decoder` 与 `json.Marshal/Unmarshal` 的区别与实践

Go 中 json.NewEncoder/Decoderjson.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 示例对比

我们用两个示例分别展示:

  1. json.NewEncoder/Decoder:直接读写 http.Request.Bodyhttp.ResponseWriter
  2. json.Marshal/Unmarshal:先读完整体,再解析和返回

🧾 公共结构体定义:

go 复制代码
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

🧪 方法一:使用 json.NewDecoderjson.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.Unmarshaljson.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": "alice@example.com"}'

📚 参考文档


希望这篇文章能帮助你理解 json.Marshal/Unmarshaljson.NewEncoder/Decoder 的差异,并选择适合你项目场景的方式。

相关推荐
再见晴天*_*2 小时前
SpringBoot 中单独一个类中运行main方法报错:找不到或无法加载主类
java·开发语言·intellij idea
lqjun08274 小时前
Qt程序单独运行报错问题
开发语言·qt
hdsoft_huge6 小时前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
风中的微尘6 小时前
39.网络流入门
开发语言·网络·c++·算法
未来之窗软件服务6 小时前
幽冥大陆(二)RDIFSDK 接口文档:布草洗涤厂高效运营的技术桥梁C#—东方仙盟
开发语言·c#·rdif·仙盟创梦ide·东方仙盟
小冯记录编程7 小时前
C++指针陷阱:高效背后的致命危险
开发语言·c++·visual studio
1uther7 小时前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎
C_Liu_7 小时前
C++:类和对象(下)
开发语言·c++
coderxiaohan8 小时前
【C++】类和对象1
java·开发语言·c++
阿幸软件杂货间8 小时前
Office转PDF转换器v1.0.py
开发语言·pdf·c#