Gin之参数获取 | 青训营笔记

147 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记

获取参数

querystring 参数

querystring指的是URL中?后面携带的参数,例如:/user/search?username=小王子&address=沙河

获取请求的querystring参数的方法有:gin.Query()gin.DefaultQuery()gin.GetQuery()

示例:

 func main() {
     r := gin.Default()
     r.GET("/user/search", func(c *gin.Context) {
         // 获取浏览器请求中携带的 querystring 参数
 ​
         // 1.Query: 参数为key,返回用户输入的值
         //username := c.Query("username")
         address := c.Query("address")
 ​
         // 2.DefaultQuery:若querystring的key不是username,则返回默认值“游客”
         //username := c.DefaultQuery("username", "游客")
 ​
         // 3. GetQuery:返回两个值,若querystring的key不是username,则第二个返回值为false
         username, ok := c.GetQuery("username")
         if !ok {
             username = "游客"
         }
 ​
         // 获取到参数后使用JSON格式输出参数
         c.JSON(http.StatusOK, gin.H{
             "username": username,
             "address":  address,
         })
     })
     r.Run(":8080")
 }

测试:

image-20220509200714666

form 参数

当前端请求的数据通过form表单提交时,获取请求数据的方法:

  • gin.PostForm()
  • gin.DefaultPostForm()

示例:

login.html 页面:

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>form</title>
 </head>
 <body>
 ​
 <form action="/use/login" method="post">
 ​
     <div>
         <label for="username">username:</label>
         <input type="text" name="username" id="username">
     </div>
     <div>
         <label for="password">password:</label>
         <input type="text" name="password" id="password">
     </div>
     <div>
         <input type="submit" value="Login">
     </div>
 </form>
 ​
 </body>
 </html>

index.html 页面:

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>index</title>
 </head>
 <body>
 <h1>Hello, {{ .username }}</h1>
 <p>Your password: {{ .password }}</p>
 </body>
 </html>

go 程序:

 func main() {
     r := gin.Default()
     // 解析html
     r.LoadHTMLFiles("./login.html", "./index.html")
 ​
     // GET /login 返回login.html页面
     r.GET("/login", func(c *gin.Context) {
         c.HTML(http.StatusOK, "login.html", nil)
     })
 ​
     // POST /login 从form表单获取的数据,返回到index.html中渲染
     r.POST("/login", func(c *gin.Context) {
 ​
         // 1.PostForm:参数key对应html页面的name值
         username := c.PostForm("username")
         password := c.PostForm("password")
 ​
         // DefaultPostForm取不到值时会返回指定的默认值
         //username := c.DefaultPostForm("username", "游客")
 ​
         c.HTML(http.StatusOK, "index.html", gin.H{
             "username": username,
             "password": password,
         })
     })
     r.Run(":8080")
 }

启动项目,访问/login

image-20220509203308939

json 参数

当前端请求的数据通过 JSON 提交时,例如向 /json 发送一个POST请求,则获取请求参数的方式如下:

 r.POST("/json", func(c *gin.Context) {
     // 注意:下面为了举例子方便,暂时忽略了错误处理
     b, _ := c.GetRawData()  // 从c.Request.Body读取请求数据
     // 定义map或结构体
     var m map[string]interface{}
     // 反序列化
     _ = json.Unmarshal(b, &m)
 ​
     c.JSON(http.StatusOK, m)
 })

更便利的获取请求参数的方式,参见下面 参数绑定

path 参数

请求的参数通过URL路径传递,例如:/user/search/杨超越/18。 获取请求URL路径中的参数的方法:

  • gin.Param()

需要在GET请求路径中使用 : 表示要传入的参数名。

示例:

 func main() {
     r := gin.Default()
     r.GET("/user/search/:username/:age", func(c *gin.Context) {
         username := c.Param("username")
         age := c.Param("age")
 ​
         c.JSON(http.StatusOK, gin.H{
             "username": username,
             "age":      age,
         })
     })
     r.Run(":8080")
 }

测试:

image-20220509204007816

参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryStringform表单JSONXML等参数到结构体中。

ShouldBind会按照下面的顺序解析请求中的数据完成绑定:

  1. 如果是 GET 请求,只使用 Form 绑定引擎(querystring)。
  2. 如果是 POST 请求,首先检查 content-type 是否为 JSONXML,然后再使用 Formform-data)。

下面的示例代码演示了.ShouldBind()强大的功能,它能够基于请求自动提取JSONform表单QueryString类型的数据,并把值绑定到指定的结构体对象。

 package main
 ​
 import (
     "github.com/gin-gonic/gin"
     "net/http"
 )
 ​
 //User Binding from JSON and form
 type User struct {
     Username string `json:"username" form:"username"`
     Password string `json:"password" form:"password"`
 }
 ​
 func main() {
     r := gin.Default()
 ​
     // 绑定JSON ({"username": "AruNi", "password": "123456"})
     r.POST("/loginJSON", func(c *gin.Context) {
         var user User
         // ShouldBind()会根据请求的Content-Type自行选择绑定器
         if err := c.ShouldBind(&user); err == nil {
             c.JSON(http.StatusOK, gin.H{
                 "username": user.Username,
                 "password": user.Password,
             })
         } else {
             c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
         }
     })
 ​
     // 绑定form表单 (username=AruNi&&password=123456)
     r.POST("/loginForm", func(c *gin.Context) {
         var user User
         // ShouldBind()会根据请求的Content-Type自行选择绑定器
         if err := c.ShouldBind(&user); err == nil {
             c.JSON(http.StatusOK, gin.H{
                 "username": user.Username,
                 "password": user.Password,
             })
         } else {
             c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
         }
     })
 ​
     // 绑定querystring (/loginQuery?username=AruNi&&password=123456)
     r.GET("/loginQuery", func(c *gin.Context) {
         var user User
         // ShouldBind()会根据请求的Content-Type自行选择绑定器
         if err := c.ShouldBind(&user); err == nil {
             c.JSON(http.StatusOK, gin.H{
                 "username": user.Username,
                 "password": user.Password,
             })
         } else {
             c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
         }
     })
 ​
     r.Run(":8080")
 }

JSON 测试:

image-20220510110942941

form 表单测试:

image-20220510111457824

querystring 测试:

image-20220510111312145