Go 的 http.ResponseWriter 不自动序列化 JSON,需手动设置 Content-Type 为 application/json; charset=utf-8 并用 json.NewEncoder(w).Encode(v) 安全编码,注意避免提前写 header 或状态码,结构体字段加 json tag,空值处理用 omitempty,错误响应须显式设状态码。

Go 的 http.ResponseWriter 本身不自动序列化 JSON,必须手动调用 json.Marshal 并设置正确的 Content-Type 头,否则前端收到的是纯文本或格式错误的响应。
用 json.NewEncoder 直接写入响应体更安全
相比先 json.Marshal 再 Write,json.NewEncoder(w).Encode(v) 能自动处理流式编码、避免中间字节切片、减少内存分配,且在编码失败时直接写入 HTTP 500 错误(前提是未写入 header)。
- 必须在调用前确保未写入任何响应头或状态码,否则
Encode会 panic - 对结构体字段需加
jsontag,如type User { Name string `json:"name"` } - 空值(nil slice/map/pointer)默认输出为
null,如需跳过用omitempty:`json:"name,omitempty"`
返回错误时别忘了设 HTTP 状态码
仅写 JSON 数据但没调用 w.WriteHeader(http.StatusBadRequest),Go 默认返回 200 OK,前端无法靠 status 判断失败。
- 常见组合:
w.WriteHeader(http.StatusNotFound)+json.NewEncoder(w).Encode(map[string]string{"error": "not found"}) - 建议封装统一错误响应函数,避免每次重复写
WriteHeader和Encode - 注意:一旦调用
WriteHeader,后续不能再修改状态码或 header
中文乱码?Content-Type 缺少 charset=utf-8
默认 Content-Type: application/json 不声明字符集,某些旧版浏览器或测试工具可能解析为 ISO-8859-1,导致中文显示为 \u4f60\u597d 或方块。
立即学习“go语言免费学习笔记(深入)”;
- 正确写法:
w.Header().Set("Content-Type", "application/json; charset=utf-8") - 如果用了
json.NewEncoder,它不会自动加 charset,必须手动设置 header - 使用
net/http的http.Error会忽略 charset,不推荐用于 JSON 错误响应
最容易被忽略的是:在中间件或 handler 链中提前写了 header(比如日志中间件调用了 w.Write),会导致后续 json.NewEncoder.Encode panic —— 这类错误没有明确报错提示,只会看到连接重置或空响应。










