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

相关推荐
SelectDB2 小时前
StarRocks 适合做日志分析吗?
数据分析·json·自动化运维
SelectDB2 小时前
为什么 JSON 正在成为分析数据库新的竞争点?
数据库·json·agent
Interview Aid1125 小时前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
CoderIsArt13 小时前
C#中UI 线程与 Dispatcher
开发语言·ui·c#
AI情绪识别开源15 小时前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
「QT(C++)开发工程师」16 小时前
C++ auto 用法详解
开发语言·c++
OPEN-F16 小时前
C++STL教程:容器适配器与实用工具
开发语言·c++
yaoxin52112317 小时前
507. Java 反射 - 在 BeanFactory 中实现依赖注入
java·开发语言
OPEN-F17 小时前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++