Gin框架系列之请求参数处理
一、GET请求处理
(一)路径参数
对于类似这样的请求:http://127.0.0.1:8080/index/12,那么如何获取最后路径中12的值呢?
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func Index(ctx *gin.Context) { id := ctx.Param("id") fmt.Println(id) ctx.String(http.StatusOK, "success!") } func main() { router := gin.Default() // 路径参数获取,如:http://127.0.0.1:8080/index/12,获取12 router.GET("/index/:id", Index) router.Run(":8080") }
在挂载路由时需要通过":"来进行匹配,然后在视图函数中通过ctx.Param方法获取。
(二)查询参数
对于类似这样的请求:http://127.0.0.1:8080/index1?id=12,那么如何获取最后路径中12的值呢?
1、ctx.Query
传参:http://127.0.0.1:8080/index1?id=12
路由:router.GET("/index1", Index1)
视图函数获取:ctx.Query("id")
2、ctx.DefaultQuery
传参:http://127.0.0.1:8080/index2
路由:router.GET("/index2", Index2)
视图函数获取:ctx.DefaultQuery("id", "0")
如果没有获取到id,就得到默认值0.
3、ctx.QueryArray
传参:http://127.0.0.1:8080/index3?id=1,2,3,4,5
路由:router.GET("/index3", Index3)
视图函数获取:ctx.QueryArray("id")
4、ctx.QueryMap
传参:http://127.0.0.1:8080/index4?user[name]=%22lily%22&user[age]=15
路由:router.GET("/index4", Index4)
视图函数获取:ctx.QueryMap("user")
(三)实例
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func Index(ctx *gin.Context) { id := ctx.Param("id") fmt.Println(id) ctx.String(http.StatusOK, "success!") } func Index1(ctx *gin.Context) { id := ctx.Query("id") fmt.Println(id) // 12 ctx.String(http.StatusOK, "success!") } func Index2(ctx *gin.Context) { id := ctx.DefaultQuery("id", "0") fmt.Println(id) // 0 ctx.String(http.StatusOK, "success!") } func Index3(ctx *gin.Context) { idList := ctx.QueryArray("id") fmt.Println(idList) // [1,2,3,4,5] ctx.String(http.StatusOK, "success!") } func Index4(ctx *gin.Context) { user := ctx.QueryMap("user") fmt.Println(user) // map[age:15 name:"lily"] ctx.String(http.StatusOK, "success!") } func main() { router := gin.Default() // 路径参数获取,如:http://127.0.0.1:8080/index/12,获取12 router.GET("/index/:id", Index) // 查询参数获取,如:http://127.0.0.1:8080/index?id=12,获取12 router.GET("/index1", Index1) router.GET("/index2", Index2) router.GET("/index3", Index3) router.GET("/index4", Index4) router.Run(":8080") }
二、POST请求处理
(一) 普通方式提交表单
1、ctx.PostForm
- 表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/post_index" method="post"> <p>用户名:<input type="text" name="username"></p> <p>密 码:<input type="password" name="password"></p> <p><input type="submit"></p> </form> </body> </html>
- 后台处理
... func PostIndex(ctx *gin.Context) { username := ctx.PostForm("username") password := ctx.PostForm("password") fmt.Printf("用户名:%s, 密码:%s", username, password) ctx.String(http.StatusOK, "提交成功!") } ...
2、ctx.PostFormMap
- 表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/post_index1" method="post"> <p>用户名:<input type="text" name="user[username]"></p> <p>密 码:<input type="password" name="user[password]"></p> <p><input type="submit"></p> </form> </body> </html>
- 后台处理
... func PostIndex1(ctx *gin.Context) { userMap := ctx.PostFormMap("user") fmt.Println(userMap) ctx.String(http.StatusOK, "提交成功!") } ...
3、ctx.DefaultPostForm、ctx.PostFormArray
- 表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/post_index2" method="post"> <p>用户名:<input type="text" name="username"></p> <p>密 码:<input type="password" name="password"></p> <p>爱 好: 读书<input type="checkbox" name="hobby" value="1"> 看电影<input type="checkbox" name="hobby" value="2"> 音乐<input type="checkbox" name="hobby" value="3"> </p> <p><input type="submit"></p> </form> </body> </html>
- 后台处理
... func PostIndex2(ctx *gin.Context) { username := ctx.PostForm("username") password := ctx.PostForm("password") age := ctx.DefaultPostForm("age", "0") hobby := ctx.PostFormArray("hobby") fmt.Printf("用户名:%s, 密码:%s, 年龄:%s, 爱好:%s", username, password, age, hobby) ctx.String(http.StatusOK, "提交成功!") } ...
4、后台主要文件
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func GetIndex(ctx *gin.Context) { ctx.HTML(http.StatusOK, "index.html", nil) } func PostIndex(ctx *gin.Context) { username := ctx.PostForm("username") password := ctx.PostForm("password") fmt.Printf("用户名:%s, 密码:%s", username, password) ctx.String(http.StatusOK, "提交成功!") } func GetIndex1(ctx *gin.Context) { ctx.HTML(http.StatusOK, "index1.html", nil) } func PostIndex1(ctx *gin.Context) { userMap := ctx.PostFormMap("user") fmt.Println(userMap) ctx.String(http.StatusOK, "提交成功!") } func GetIndex2(ctx *gin.Context) { ctx.HTML(http.StatusOK, "index2.html", nil) } func PostIndex2(ctx *gin.Context) { username := ctx.PostForm("username") password := ctx.PostForm("password") age := ctx.DefaultPostForm("age", "0") hobby := ctx.PostFormArray("hobby") fmt.Printf("用户名:%s, 密码:%s, 年龄:%s, 爱好:%s", username, password, age, hobby) ctx.String(http.StatusOK, "提交成功!") } func main() { router := gin.Default() router.LoadHTMLGlob("template/*") // ctx.PostForm router.GET("/get_index", GetIndex) router.POST("/post_index", PostIndex) // ctx.PostFormMap router.GET("/get_index1", GetIndex1) router.POST("/post_index1", PostIndex1) // ctx.DefaultPostForm、ctx.PostFormArray router.GET("/get_index2", GetIndex2) router.POST("/post_index2", PostIndex2) router.Run(":8080") }
(二)Ajax方式提交表单
ajax的后台处理逻辑与普通的表单的提交的处理方式基本相同,只不过在返回的时候需要返回json数据,前台使用回调函数进行处理。
- 前台
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/js/jquery-3.6.0.js"></script> </head> <body> <form> <p>用户名:<input id="username" type="text"></p> <p>密码:<input id="password" type="password"></p> <p><input type="button" value="提交" id="btn_submit"></p> </form> <script> var btn = document.getElementById("btn_submit") btn.onclick = function (ev) { var username = document.getElementById("username").value var password = document.getElementById("password").value $.ajax({ url: '/post_index', type: 'POST', data: { username: username, password: password }, success: function (data) { alert(data) // 响应成功的回调函数 }, fail: function (data) { } }) } </script> </body> </html>
- 后台
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func GetIndex(ctx *gin.Context) { ctx.HTML(http.StatusOK, "index.html", nil) } func PostIndex(ctx *gin.Context) { username := ctx.PostForm("username") password := ctx.PostForm("password") fmt.Println(username, password) data := map[string]interface{}{ "code": 2000, "message": "成功", } ctx.JSON(http.StatusOK, data) } func main() { router := gin.Default() router.LoadHTMLGlob("template/*") router.Static("/static", "static") router.GET("/get_index", GetIndex) router.POST("/post_index", PostIndex) router.Run(":8080") }
三、参数绑定
无论时get请求的参数还是post请求的请求体,在后台都需要通过对应的方法来获取对应参数的值,那么有没有一种方式能够让我们定义好请求数据的格式,然后自动进行获取,这里可以通过参数绑定的方式来进行处理。它能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象。
这里以get请求的查询参数为例:
- 请求格式
http://127.0.0.1:8080/index?username=%22llkk%22&password=%22123%22
- 后台处理
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) type User struct { Username string `form:"username" json:"username"` Password string `form:"password" json:"password"` } func Index(ctx *gin.Context) { var user User err := ctx.ShouldBind(&user) fmt.Println(err) fmt.Println(user.Username, user.Password) // "llkk" "123" ctx.String(http.StatusOK, "success") } func main() { router := gin.Default() router.GET("/index", Index) router.Run(":8080") }