0

0

如何在 Go 中正确读取 HTTP 请求的查询参数与请求体数据

心靈之曲

心靈之曲

发布时间:2026-01-03 19:42:08

|

861人浏览过

|

来源于php中文网

原创

如何在 Go 中正确读取 HTTP 请求的查询参数与请求体数据

本文详解 go 的 net/http 包中 `req.body` 为空的原因,并提供针对 get/post 请求分别获取参数的规范做法:get 应使用 `req.url.query()` 或 `req.parseform()` + `req.form`,而 post 的 json 数据才应通过 `json.decoder(req.body)` 解析。

在 Go 的 net/http 中,*http.Request.Body 仅承载 HTTP 请求体(request body)中的原始字节,例如 POST/PUT 请求中以 Content-Type: application/json 发送的 JSON 负载。它完全不包含 URL 查询参数(query string)——这些参数位于请求行中(如 /step?steps=1&direction=1),由 req.URL.Query() 直接解析,与 Body 无关。

你遇到的 req.Body 为 nil 或解码失败,根本原因在于:
✅ 你的 AJAX 请求使用的是 method: "get",浏览器将所有 data 自动序列化为 URL 查询参数(见示例 URL),此时 HTTP 请求体为空,req.Body 自然不可读或已关闭;
❌ 调用 json.NewDecoder(req.Body).Decode(&v) 对空 Body 解码必然失败(io.EOF 或 invalid character),且 log.Println(v) 输出 是因解码失败后 v 未被赋值,仍为零值 interface{}(即 nil)。

✅ 正确处理方式(按请求方法区分)

1. 对于 GET 请求(推荐:直接解析 URL 查询参数)

func stepHandler(res http.ResponseWriter, req *http.Request) {
    // 方法一:直接获取 URL 查询参数(最轻量、无需 ParseForm)
    steps := req.URL.Query().Get("steps")           // "1"
    direction := req.URL.Query().Get("direction")   // "1"
    cellsJSON := req.URL.Query().Get("cells")       // "[{\"row\":11,...}]"

    // 方法二:ParseForm 后统一访问(对 GET/POST 均有效,但 GET 下等价于 Query)
    err := req.ParseForm()
    if err != nil {
        http.Error(res, "Invalid form data", http.StatusBadRequest)
        return
    }
    steps = req.FormValue("steps")      // 等价于 req.URL.Query().Get("steps")
    cellsJSON = req.FormValue("cells")

    // 解析 JSON 字符串字段(注意:cells 是 URL 编码后的字符串,需二次 JSON 解码)
    var cells []map[string]int
    if err := json.Unmarshal([]byte(cellsJSON), &cells); err != nil {
        http.Error(res, "Invalid cells JSON", http.StatusBadRequest)
        return
    }

    log.Printf("Steps: %s, Direction: %s, Cells: %+v", steps, direction, cells)
}

2. 对于 POST 请求(发送 JSON Body)

若需真正使用 req.Body,客户端应改为 POST 并设置 Content-Type: application/json:

// 客户端 AJAX(POST + JSON Body)
$.ajax({
  url: "/step",
  method: "POST",
  contentType: "application/json",
  data: JSON.stringify({
    steps: parseInt($("#step-size").val()),
    direction: $("#step-forward").prop("checked") ? 1 : -1,
    cells: painted // 直接传数组,无需 stringify
  }),
  success: function(data) { /* ... */ }
});

服务端则可安全读取 Body:

你好星识
你好星识

你的全能AI工作空间

下载
func stepHandler(res http.ResponseWriter, req *http.Request) {
    if req.Method != "POST" {
        http.Error(res, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    var payload struct {
        Steps     int      `json:"steps"`
        Direction int      `json:"direction"`
        Cells     []struct { Row, Column int } `json:"cells"`
    }

    // Body 可被 json.Decoder 读取(自动处理 Content-Length 和关闭)
    if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
        http.Error(res, "Invalid JSON", http.StatusBadRequest)
        return
    }
    defer req.Body.Close() // 显式关闭(虽 Decoder 通常已关闭,但属最佳实践)

    log.Printf("Payload: %+v", payload)
}

⚠️ 关键注意事项

  • req.Body 只能读取一次:读取后会被耗尽,后续再调用 req.ParseForm() 或 json.Decoder 将失败(除非提前 ioutil.ReadAll 并重置 req.Body)。
  • req.ParseForm() 对 GET 是冗余的:它内部会检查 req.Method,若为 GET 则直接解析 req.URL.RawQuery,无需额外开销。
  • 永远校验 err:json.Decode 失败时 v 不会被修改,直接打印 v 会输出零值(如 nil, 0, ""),易造成误判。
  • 生产环境务必设置超时与限长:避免恶意大请求体阻塞服务,建议配合 http.MaxBytesReader 使用。

总结:理解 HTTP 协议分层是关键——URL 参数属于请求行,Body 属于消息体。Go 的 net/http 严格遵循此规范,选择正确的 API(URL.Query() vs Body)才能高效、健壮地处理各类请求。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

403

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

530

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

308

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

ajax教程
ajax教程

php中文网为大家带来ajax教程合集,Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。php中文网还为大家带来ajax的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

146

2023.06.14

ajax中文乱码解决方法
ajax中文乱码解决方法

ajax中文乱码解决方法有设置请求头部的字符编码、在服务器端设置响应头部的字符编码和使用encodeURIComponent对中文进行编码。本专题为大家提供ajax中文乱码相关的文章、下载、课程内容,供大家免费下载体验。

159

2023.08.31

ajax传递中文乱码怎么办
ajax传递中文乱码怎么办

ajax传递中文乱码的解决办法:1、设置统一的编码方式;2、服务器端编码;3、客户端解码;4、设置HTTP响应头;5、使用JSON格式。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

109

2023.11.15

ajax网站有哪些
ajax网站有哪些

使用ajax的网站有谷歌、维基百科、脸书、纽约时报、亚马逊、stackoverflow、twitter、hacker news、shopify和basecamp等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.09.24

漫画合集pdf网盘入口_漫画解说合集一口气看完
漫画合集pdf网盘入口_漫画解说合集一口气看完

精选高人气漫画合集PDF,一站式网盘入口直达!深度漫画解说整合,一口气看完经典与新作,剧情梳理清晰,省时省力,追漫党必看合集。

9

2026.01.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号