
本文详解 go web 服务中 req.body 为空或解析失败的常见原因,重点解决因 json 格式错误、未检查解码错误、重复读取 body 导致的数据丢失问题,并提供健壮的请求体解析实践。
本文详解 go web 服务中 req.body 为空或解析失败的常见原因,重点解决因 json 格式错误、未检查解码错误、重复读取 body 导致的数据丢失问题,并提供健壮的请求体解析实践。
在 Go 中处理 HTTP POST 请求时,许多开发者会遇到 req.Body 显示为类似 &{%!s(*io.LimitedReader=...)} 的不可读内容,或解析后结构体字段为空(如 Name 为 "")。这并非 Go 的 Bug,而是由三个关键因素共同导致:JSON 字符串格式非法、忽略解码错误、以及对 req.Body 的误用。
首先,检查你从 Postman 发送的原始 JSON。问题中提供的示例:
{
“name”: "foo"
}表面看似合法,但注意第一个引号 “ 是中文全角双引号(Unicode U+201C),而非标准 ASCII 双引号 "(U+0022)。Go 的 json 包严格遵循 RFC 8259,仅接受 ASCII 引号。该非法字符会导致 json.Decoder.Decode() 立即返回语法错误(如 invalid character '' looking for beginning of object key string),而原代码未捕获该错误,致使 t.Name 保持零值,且 req.Body 因已尝试读取而处于耗尽(exhausted)状态。
其次,req.Body 是一个 io.ReadCloser,只能被完整读取一次。调用 json.NewDecoder(req.Body).Decode(&t) 会消费整个 Body 流;随后若再尝试打印 req.Body(如 fmt.Fprintf(rw, "%s\n", req.Body)),实际输出的是 Body 接口本身的内存地址描述(即你看到的 %!s(...)),而非其内容——因为流已关闭或无剩余数据。
✅ 正确做法如下:
- 始终检查解码错误;
- 避免直接打印 req.Body 接口,如需调试原始内容,应先用 io.ReadAll 读取并缓存;
- 确保 Postman 中 Content-Type 为 application/json,并在 Body → raw 下选择 JSON 格式发送。
以下是修复后的完整示例代码:
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type Input struct {
Name string `json:"name"`
}
func test(w http.ResponseWriter, r *http.Request) {
// ✅ 检查请求方法
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// ✅ 解析 JSON 并显式处理错误
var input Input
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
log.Printf("JSON decode error: %v", err)
http.Error(w, "Invalid JSON format", http.StatusBadRequest)
return
}
defer r.Body.Close() // ✅ 始终关闭 Body
// ✅ 安全响应:使用 input.Name 而非 req.Body
fmt.Fprintf(w, "Received name: %s", input.Name)
}
func main() {
http.HandleFunc("/test", test)
fmt.Println("Server starting on :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}? 关键注意事项:
- Postman 中务必使用英文半角引号 "name",禁用智能引号;
- 不要省略 defer r.Body.Close(),防止资源泄漏;
- 若需同时记录原始请求体(如日志审计),可先执行 bodyBytes, _ := io.ReadAll(r.Body),再用 bytes.NewReader(bodyBytes) 重建可重用的 Reader;
- 生产环境建议使用中间件统一处理 Body 解析与验证,避免每个 handler 重复逻辑。
遵循以上规范,即可稳定获取并解析来自 Postman 或任意客户端的 JSON 请求体。


















