获取 Query 参数
Query 参数又叫 Querystring 参数,是 URL 的?后面的一串字符串。
Demo 代码如下:
r.GET("/home", func(c *gin.Context) { username := c.Query("username") password := c.DefaultQuery("password", "******") addr := c.QueryArray("addr") class := c.QueryMap("class") age, ok := c.GetQuery("age") if ok = true { fmt.Println(ok) } c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "addr": addr, "class": class, "age": age, })})结果如下:
总结:
Query()用来获取参数
使用 DefaultQuery()方法时,如果没有相应的参数,就会使用 defaultValue 的值来代替。
QueryArray()和 QueryMap()方法分别获取切片类型和字典类型的参数
GetQuery()方法返回两个值,一个 value,一个 bool 值。当能够获取到相应的值时,bool 值=true;当不能够获取到相应的值时,value 为空,bool 值=false。
需要注意的是切片类型的参数和字典类型的参数的写法。
- 切片:addr=aaa&addr=bbb
- 字典:class[专业]=软件工程&class[年级]=大一
获取 Path 参数
Path 参数就是路径参数,也就是 URL 中斜杠和斜杠之间的参数
Demo 代码如下:
r.GET("/user/info/:username/:password/:hobby", func(c *gin.Context) { username := c.Param("username") password := c.Param("password") hobby := c.Param("hobby") params := c.Params c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "hobby": hobby, "params": params, })})结果如下:
总结:
把获取的 Path 参数的前面加上“ : ”,就表示这个 Path 参数是要获取的参数。
Param()方法只能一个一个的获取参数。
Params()方法是一次性获取所有的 Path 参数,返回的是 Params 类型,该类型的定义如下
gotype Param struct { Key string Value string}type Params []Param当有一部分 Path 参数获取不到时,前面获取到的 Path 参数都会全部丢弃。其本质原因是底层使用 rang 遍历所有的 Path 参数,如果没有相应的参数,会把整个 params 切片置为空。源码如下:
gofunc (ps Params) Get(name string) (string, bool) { for _, entry := range ps { if entry.Key == name { return entry.Value, true } } return "", false //注意:并不是将entry.Value置为nil,而是将整个切片置为空。}func (ps Params) ByName(name string) (va string) { va, _ = ps.Get(name) return}func (c *Context) Param(key string) string { return c.Params.ByName(key)}
获取 Form 表单参数
Demo 代码如下:
r.POST("/info", func(c *gin.Context) { username := c.PostForm("username") password := c.DefaultPostForm("password", "******") hobby := c.PostFormArray("hobby") sex, ok := c.GetPostForm("sex") if ok != true { fmt.Println(ok) } c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "sex": sex, "hobby": hobby, })})结果如下:
总结:
- PostForm()方法获取表单参数
- 使用 DefaultPostForm()方法如果没有获取到参数,会有默认值代替
- PostFormArray()获取数组对象的表单参数
- GetPostForm()方法返回两个值,第一个是表单参数,第二个是 bool 值
获取 Json 参数
Demo 代码如下:
r.POST("/json", func(c *gin.Context) { var m map[string]interface{} body, err := c.GetRawData() //从请求体(body)中获取json数据 if err = nil { fmt.Println(err.Error()) } err = json.Unmarshal(body, &m) if err = nil { fmt.Println(err.Error()) } name := m["name"] email := m["email"] c.JSON(http.StatusOK, gin.H{ "name": name, "email": email, })})结果如下:
总结:
GetRawData()方法是从请求体(body)中获取原始的 json 数据
GetRawData()底层使用 ioutil 包里面的 ReadAll()方法来读取数据,ReadAll()方法底层使用 io 包里面的 ReadAll()函数,ReadAll()函数的源码如下:
gofunc ReadAll(r Reader) ([]byte, error) { b := make([]byte, 0, 512) for { if len(b) == cap(b) { // Add more capacity (let append pick how much). b = append(b, 0)[:len(b)] } n, err := r.Read(b[len(b):cap(b)]) b = b[:len(b)+n] if err = nil { if err == EOF { err = nil } return b, err } }}源码分析可以看这篇文章:
获取请求头中的数据
Demo 代码如下:
r.GET("/header", func(c *gin.Context) { token := c.GetHeader("Authorization") c.JSON(http.StatusOK, gin.H{ "Authorization": token, })})结果如下:
- GetHeader()方法用于获取请求头信息
- 设置请求头的方法有两种:
- c.Header(“Authorization”, “xxx.yyy.zzz”)
- c.Writer.Header().Set(“Authorization”, “xxx.yyy.zzz”)
数据绑定
基于请求的 Content-Type 识别请求数据类型并利用反射机制自动提取请求中 QueryString、form 表单、JSON、XML 等参数到结构体中。 下面的示例代码演示了 BindJSON()和 ShouldBindJSON,它能够基于请求自动提取 JSON 类型的数据,并把值绑定到指定的结构体对象。
Demo 代码如下:
type Login struct { Username string `json:"username"` Password string `json:"password"`}r.GET("/bindJson", func(c *gin.Context) { var login Login err := c.BindJSON(&login) if err != nil { fmt.Println(err.Error()) } username := login.Username password := login.Password c.JSON(http.StatusOK, Login{ Username: username, Password: password, }, )})r.GET("/shouldBindJson", func(c *gin.Context) { var login Login err := c.ShouldBindJSON(&login) if err != nil { fmt.Println(err.Error()) } username := login.Username password := login.Password c.JSON(http.StatusOK, Login{ Username: username, Password: password, }, )})结果如下:

总结:
- 数据绑定是利用结构体的反射机制来实现的,只要结构体里面有相应的 Tag 标签,就能实现对应数据类型的绑定。
- ShouldBindxxx 和 Bindxxx 区别:如果 Bindxxx 没有绑定到数据,会在 Header 中添加 400 的返回信息,而 ShouldBindxxx 不会。验证结果如下:
