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 的差异,并选择适合你项目场景的方式。

相关推荐
AndrewHZ16 分钟前
【python与生活】如何用Python写一个简单的自动整理文件的脚本?
开发语言·python·生活·脚本·文件整理
拉法豆粉18 分钟前
在压力测试中如何确定合适的并发用户数?
java·开发语言
枯萎穿心攻击36 分钟前
Unity VS UE 性能工具与内存管理
开发语言·游戏·unity·ue5·游戏引擎·虚幻·虚幻引擎
老赵的博客1 小时前
c++ 常用接口设计
开发语言·c++
binbinaijishu881 小时前
Python爬虫入门指南:从零开始的网络数据获取之旅
开发语言·爬虫·python·其他
chenglin0161 小时前
Logstash_Input插件
java·开发语言
3壹1 小时前
单链表:数据结构中的高效指针艺术
c语言·开发语言·数据结构
不过普通话一乙不改名2 小时前
第四章:并发编程的基石与高级模式之Select语句与多路复用
开发语言·golang
JCBP_3 小时前
QT(1)
开发语言·汇编·c++·qt
可峰科技3 小时前
qt配置ros2环境,简单版本
开发语言·qt