Gin 快速开发 | 02 - Gin 请求

778 阅读4分钟

我正在参与掘金创作者训练营第5期,点击了解活动详情

一、Gin 请求与请求解析

GET 传参方式与参数解析

GET 请求可以通过请求地址传递参数,具体有两种;一种是将传递的参数放在请求 URI 中,既类似 /user/100000 这种形式,第二种是在请求 URI 后通过 Key-Value 方式传递参数,既类似 /user?username=tony&age=20 这种形式。

新建 url_param.go 文件,在该文件中测试 GET 请求的几种传参形式。

无参形式

在 url_param.go 文件添加 NoParamRouterHandler 函数,该函数无须处理任何参数,可以直接返回响应。

在 main 函数中定义路由并启动服务。

// filename: url_param.go

package main

//noinspection ALL
import (
   "fmt"
   "github.com/gin-gonic/gin"
   "net/http"
)

//noinspection ALL
func main(){
   r := gin.Default()
   // 设置路由
   r.GET("/no_param", NoParamRouterHandler)

   fmt.Println("Running at http://localhost:8000")
   r.Run(":8000")
}

func NoParamRouterHandler(c *gin.Context){
   c.String(http.StatusOK, "无参路由的映射函数")
}

启动服务

image.png

在浏览器中输入 /no_param,无须传递任何参数即可获取响应。

image.png

路径参数

在请求路径中传递参数,可以通过 Param 函数获取,在定义路由时要通过 /:参数名 的形式定义。

在 url_param.go 文件添加 PathParamRouterHandler 函数,该函数可以获取请求 URI 中的参数。

定义路由时要注意路由的形式。

// filename: url_param.go

//noinspection ALL
func main(){
   r := gin.Default()
   // r.GET("/no_param", NoParamRouterHandler)

   // 路径参数,定义路由
   r.GET("/param/:userId", PathParamRouterHandler)

   fmt.Println("Running at http://localhost:8000")
   r.Run(":8000")
}

// 
func PathParamRouterHandler(c *gin.Context){
   userId := c.Param("userId")

   c.String(http.StatusOK, fmt.Sprintf("路径参数为:%v", userId))
}

重新启动应用,在浏览器中访问 /param/100

image.png

页面显示已经成功获取到请求 URI 中传递的参数。

URL 参数

当参数在请求中通过 K-V 的方式传递时,可以通过 DefaultQuery 或者 Query 方法获取。

DefaultQuery() 在查询参数不存在时,返回默认值,而 Query() 在查询的参数不存在时,返回空字符串。

在 url_param.go 文件添加 UrlParamRouterHandler 函数,该函数可以获取请求中的 K-V 形式的参数。

// filename: url_param.go

//noinspection ALL
func main(){
   r := gin.Default()
   // r.GET("/no_param", NoParamRouterHandler)

   // 路径参数
   // r.GET("/param/:userId", PathParamRouterHandler)

   // URL 参数
   r.GET("/url/param", UrlParamRouterHandler)

   fmt.Println("Running at http://localhost:8000")
   r.Run(":8000")
}

func UrlParamRouterHandler(c *gin.Context) {
   username := c.Query("username")
   c.String(http.StatusOK, 
      fmt.Sprintf("URL 参数为:%v", username))
}

重新启动应用,浏览器访问 /param?username=tony

image.png

页面显示已经成功获取到请求路径中传递的 K-V 形式的参数。

设置默认值

当指定的参数并没有在请求中传递时,可以通过 DefaultQuery 设置默认值

func UrlParamRouterHandler(c *gin.Context) {
   username := c.Query("username")

   age := c.DefaultQuery("age", "18")
   c.String(http.StatusOK, 
      fmt.Sprintf("URL 参数 username 的值为:%v, age 的值为:%v, 如果 age 参数未传值,默认值为:%v", 
         username, age, age))
}

重启应用,浏览器中输入 /param?username=tony&age=20

image.png

页面已经获取请求中传递的参数

在浏览器中输入 /param?username=tony,只传递 username 参数,不传递 age 参数

image.png

页面获取到 age 参数设置的默认值。

POST 请求传参方式与参数解析

不同于 GET 请求,POST 请求的参数是放在请求体中的,其他面向对象语言如 Java,Python 的 Web 框架在处理 POST 请求的请求体中传递的数据时都是封装为一个对象。在 Gin 中可以把请求体传递的数据封装为一个结构体。

我们可以基于请求的 Content-Type 识别请求数据类型并利用反射机制,自动解析获取请求中 QueryString、form 表单、JSON、XML 等参数到结构体中。

获取请求体中共的数据需要使用 ShouldBind 函数。

新建 body_param.go 文件,以登录为例,首先新建一个结构体 User,结构体中包含两个属性用户名和密码,既用来保存登录时输入的用户名和密码。

新建 LoginHandler 函数,在该函数中实例化 User 结构体,并使用 ShouldBind 函数将请求体中的数据封装到 User 实例化结构体中。

最后在 main 函数中定义路由,映射到到 LoginHandler 函数上。

// filename: body_param.go

package main

//noinspection ALL
import (
   "fmt"
   "github.com/gin-gonic/gin"
   "net/http"
)

//noinspection ALL
func main(){
   r := gin.Default()

   r.POST("/login", LoginHandler)

   fmt.Println("Running at http://localhost:8000")
   r.Run(":8000")
}

type User struct {
   Username string `json:"username"`
   Password string `json:"password"`
}

func LoginHandler(c *gin.Context){

   var user User

   if err := c.ShouldBind(&user); err != nil {
      c.String(http.StatusOK, "参数校验失败")
   }

   fmt.Println("登录用户为:", user)
   c.String(http.StatusOK, "OK")
}

启动服务

image.png

在 Postman 中创建一个 POST 请求,请求体中输入 JSON 格式的数据,点击 Send 按钮

image.png

返回 OK,说明请求成功。

查看控制台,成功输入请求中的 JSON 数据,并封装在了结构体中。

image.png