在Go语言编写的HTTP服务器中,处理GET请求的相关参数需要根据参数的传递位置采用不同的解析方式,首先要明确常规场景下GET请求的参数大多放在URL的查询字符串中,而非请求体里。
常规GET请求查询参数解析
大多数GET请求的参数会拼接在URL的查询字符串部分,Go的net/http标准库提供了便捷的方法解析这部分参数。首先需要通过Request结构体的ParseForm方法解析表单数据,之后就可以通过Form或者URL.Query获取对应的参数值。
以下是一个简单的示例,展示如何解析GET请求的查询参数:
package main
import (
"fmt"
"net/http"
)
func getHandler(w http.ResponseWriter, r *http.Request) {
// 解析表单数据,包含查询参数和可能的表单数据
err := r.ParseForm()
if err != nil {
http.Error(w, "解析请求参数失败", http.StatusBadRequest)
return
}
// 获取单个查询参数,比如参数名为name
name := r.FormValue("name")
// 获取所有同名参数,比如参数名为tags
tags := r.Form["tags"]
// 也可以通过URL.Query()直接获取查询参数
age := r.URL.Query().Get("age")
fmt.Fprintf(w, "name: %s, tags: %v, age: %s", name, tags, age)
}
func main() {
http.HandleFunc("/get", getHandler)
http.ListenAndServe(":8080", nil)
}
GET请求携带请求体的场景处理
虽然HTTP协议没有禁止GET请求携带请求体,但这类使用方式并不符合常规约定,多数客户端和服务器也不会默认处理GET请求的请求体。如果确实有业务需要让GET请求携带请求体,比如传递JSON格式的数据,就需要手动读取请求体内容再进行解析。
以下是读取并解析GET请求JSON请求体的示例:
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type GetRequestBody struct {
ID int `json:"id"`
Type string `json:"type"`
}
func getWithBodyHandler(w http.ResponseWriter, r *http.Request) {
// 读取请求体内容
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "读取请求体失败", http.StatusBadRequest)
return
}
defer r.Body.Close()
var req GetRequestBody
// 解析JSON格式的请求体
err = json.Unmarshal(body, &req)
if err != nil {
http.Error(w, "解析请求体失败", http.StatusBadRequest)
return
}
fmt.Fprintf(w, "解析到的请求体内容:id=%d, type=%s", req.ID, req.Type)
}
func main() {
http.HandleFunc("/get-body", getWithBodyHandler)
http.ListenAndServe(":8080", nil)
}
注意事项
- 调用
ParseForm方法后,会同时解析URL查询参数和POST请求的表单数据,对于GET请求来说,只会解析到查询参数,不会影响后续操作。 - 如果GET请求携带了请求体,部分中间件或者代理服务器可能会忽略或者丢弃请求体内容,因此非必要场景不建议使用GET请求传递请求体数据。
- 获取参数时,
FormValue方法只能获取同名参数的第一个值,如果需要获取所有同名参数,需要使用Form["参数名"]的方式。
需要特别注意的是,HTTP协议的常规实践中,GET请求的参数应当放在URL查询字符串中,请求体通常用于POST、PUT等请求方法传递数据,遵循规范可以避免很多兼容性问题。