请求参数: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 一族就能覆盖绝大多数取值场景。下一章把这些参数结构化:用结构体一次完成绑定与校验。

笔记加载中…