请求参数:Query 与表单参数
本章解决什么问题:除了路径参数,请求里还有 URL 查询串(GET 常用)与表单体(POST 常用)。本章讲 Query 一族与 PostForm 一族 API 的用法与差异,回答“参数到底传没传”这类问题。
Query 参数
查询串位于 ? 之后,形如 /search?q=gin&page=2。Gin 在 *gin.Context 上提供了取值族:
- c.Query("q"):取第一个值,不存在返回空串;
- c.GetQuery("q"):返回 (值, 是否存在),可区分“没传”与“传了空值”;
- c.DefaultQuery("q", "gin"):不存在时返回默认值;
- c.QueryArray("tag"):同名多值,?tag=a&tag=b 返回 ["a","b"];
- c.QueryMap("m"):把 ?m[k1]=v1&m[k2]=v2 解析成 map。
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/search", func(c *gin.Context) {
q := c.DefaultQuery("q", "gin")
page := c.DefaultQuery("page", "1")
tags := c.QueryArray("tag")
c.JSON(200, gin.H{"q": q, "page": page, "tags": tags})
})
r.Run(":8080")
}
需要判断某个键是否真的出现时用 Get 一族;只想要“有值就用、没值用兜底”时用 Default 一族。
表单参数
表单体通常来自 <form enctype="application/x-www-form-urlencoded"> 或客户端按表单编码 POST 的键值对。对应 API 与 Query 一族平行:c.PostForm、c.GetPostForm、c.DefaultPostForm、c.PostFormArray。
r.POST("/login", func(c *gin.Context) {
name := c.PostForm("username")
remember, present := c.GetPostForm("remember") // 区分未勾选与空值
c.JSON(200, gin.H{
"name": name,
"remember": remember,
"present": present,
})
})
上面示例中 present 表示客户端是否提交了 remember 字段,与值本身无关。
注意事项
- Query 与 PostForm 各自只读自己通道的值;同名键在两个通道里互不干扰,按需选用。
- 文件上传属于 multipart/form-data,用 PostForm 读不到字段,需先解析 multipart(第 17、18 章)。
- 参数较多、需要类型转换与校验时,优先用 c.ShouldBind 绑定到结构体(下一章),比逐个 Get 更省事。
关键点
- Get 一族返回的布尔值是判断“参数真的传了”的可靠手段,Default 一族做不到这一点。
- Query/PostForm 返回的都是字符串,数值与布尔需自行转换或用结构体绑定。
- 路径参数、查询串、表单是三个独立的数据通道,别混为一谈。
小结
Query 与表单取值 API 一一对应、规则一致,掌握 Get 一族与 Array 一族就能覆盖绝大多数取值场景。下一章把这些参数结构化:用结构体一次完成绑定与校验。