Go 中的 json.Encoder 功能详解

json.Encoder 是 Go 标准库 encoding/json 中提供的高效 JSON 编码工具,与 json.Marshal 相比,它更适合流式数据或需要直接写入输出流(如 HTTP 响应)的场景。

基本用法

1. 创建 Encoder

import (
    "encoding/json"
    "os"
)

func main() {
    // 通常包装一个 io.Writer (如文件、网络连接等)
    enc := json.NewEncoder(os.Stdout) // 输出到标准输出
}

2. 编码数据

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

user := User{1, "张三"}

// 直接编码到输出流
if err := enc.Encode(user); err != nil {
    panic(err)
}
// 输出: {"id":1,"name":"张三"}

核心特性

1. 流式处理(内存高效)

// 适合处理大数据集
users := []User{
    {1, "Alice"},
    {2, "Bob"},
    {3, "Charlie"},
}

for _, user := range users {
    if err := enc.Encode(user); err != nil {
        log.Fatal(err)
    }
    // 每次编码后立即写入,不占用大内存
}

2. 自定义配置

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")    // 设置缩进(美化输出)
enc.SetEscapeHTML(false)     // 禁用HTML字符转义

3. 直接写入 HTTP 响应(Web开发常用)

func handler(w http.ResponseWriter, r *http.Request) {
    data := map[string]interface{}{
        "status":  "success",
        "message": "操作成功",
    }

    w.Header().Set("Content-Type", "application/json")
    enc := json.NewEncoder(w)
    if err := enc.Encode(data); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

json.Marshal 的关键区别

特性 json.Encoder json.Marshal
输出目标 直接写入 io.Writer 返回 []byte
内存使用 流式处理,更节省内存 需要完整内存存储结果
使用场景 HTTP 响应、大文件写入 需要中间 JSON 数据的场景
额外功能 可设置缩进、HTML转义等
错误处理 每次 Encode() 返回错误 单次返回错误

高级用法

1. 自定义 JSON 字段处理

type CustomTime time.Time

func (ct CustomTime) MarshalJSON() ([]byte, error) {
    return []byte(`"` + time.Time(ct).Format("2006/01/02") + `"`), nil
}

// 使用时会自动调用自定义的 MarshalJSON 方法

2. 处理特殊数据类型

enc.SetEscapeHTML(false) // 默认true,会转义 &, <, > 等字符

3. 性能优化技巧

// 复用 buffer 提高性能
var buf bytes.Buffer
enc := json.NewEncoder(&buf)

// 预热编码器(避免首次编码的初始化开销)
enc.Encode(nil) 
buf.Reset()

实际应用场景

  1. HTTP API 响应

    func JSONResponse(w http.ResponseWriter, statusCode int, data interface{}) {
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(statusCode)
        json.NewEncoder(w).Encode(data)
    }
  2. 日志记录

    func logJSON(data interface{}) {
        enc := json.NewEncoder(logFile)
        enc.SetIndent("", "  ")
        enc.Encode(data)
    }
  3. 大数据处理

    // 逐行处理大JSON文件
    for _, bigData := range hugeDataset {
        if err := enc.Encode(bigData); err != nil {
            // 处理错误
        }
        // 写入换行符或其他分隔符
        out.Write([]byte("\n")) 
    }

json.Encoder 是处理 JSON 输出的高效工具,特别适合网络编程和需要控制内存使用的场景。