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

相关推荐
小狗丹尼40024 分钟前
JSON 基础认知、数据转换与 Flask 前后端交互全解
python·flask·json
1104.北光c°31 分钟前
滑动窗口HotKey探测机制:让你的缓存TTL更智能
java·开发语言·笔记·程序人生·算法·滑动窗口·hotkey
for_ever_love__1 小时前
Objective-C学习 NSSet 和 NSMutableSet 功能详解
开发语言·学习·ios·objective-c
似水明俊德8 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
Thera7778 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
炘爚9 小时前
C语言(文件操作)
c语言·开发语言
阿蒙Amon9 小时前
C#常用类库-详解SerialPort
开发语言·c#
凸头9 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun31415910 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
Moksha26210 小时前
5G、VoNR基本概念
开发语言·5g·php