我正在参与掘金创作者训练营第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, "无参路由的映射函数")
}
启动服务
在浏览器中输入 /no_param,无须传递任何参数即可获取响应。
路径参数
在请求路径中传递参数,可以通过 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
页面显示已经成功获取到请求 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
页面显示已经成功获取到请求路径中传递的 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
页面已经获取请求中传递的参数
在浏览器中输入 /param?username=tony,只传递 username 参数,不传递 age 参数
页面获取到 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")
}
启动服务
在 Postman 中创建一个 POST 请求,请求体中输入 JSON 格式的数据,点击 Send 按钮
返回 OK,说明请求成功。
查看控制台,成功输入请求中的 JSON 数据,并封装在了结构体中。