Golang Gin 获取Restful参数、URL查询参数,Form 表单参数,JSON格式参数
前言
http请求中, 可以通过URL查询参数提交数据到服务器,可以通过post的json方式,还有一直方式就是Form表单。Form表单相比URL查询参数,用户体验好,可以承载更多的数据,尤其是文件上传时,特别方便。
这里推荐 飞雪无情的博客;写了一些列的gin的使用教程,很时候新手学习
如果想对gin有一个完整的了解,也可以查看这个 Gin框架中文文档;文档相对比较完整一些
正文
Gin获取Restful路由参数
Gin实现路由参数非常简单:
func main() {
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.String(200, "The user id is %s", id)
})
r.Run(":8080")
}
Gin的路由采用的是
httprouter
开源库,所以它的路由参数的定义和httprouter
也是一样的。
冒号匹配(😃
/users/:id 就是一种路由匹配模式,也是一个通配符,其中:id就是一个路由参数
我们可以通过
c.Param("id")
获取定义的路由参数的值。
/users/:id这种匹配模式是精确匹配的,只能匹配一个;例如:
Pattern: /users/:id
/users/123 匹配
/users/哈哈 匹配
/users/123/go 不匹配
/users/ 不匹配
星号路由参数(*)
上面我们介绍的是:号的路由参数,这种路由参数最常用。还有一种不常用的就是*号类型的参数,表示匹配所有。
以/users/*id
为例:
我们可以通过
c.Param("id")
获取定义的路由参数的值。
Pattern: /users/*id
/users/123 匹配
/users/哈哈 匹配
/users/123/go 匹配
/users/ 匹配
URL查询参数(query parames)
URL查询参数简称为URL参数,是存在于我们请求的URL中,以?为起点,后面的k=v&k1=v1&k2=v2这样的字符串就是查询参数,例如:
http://127.0.0.1:8080/users?name=zzx&age=18
获取URL查询参数的方法有多个,我们分别介绍一下,案例:
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
// Query 就是最常用的一个方法
c.String(200, c.Query("wechat"))
})
r.Run(":8080")
}
/** 方便整理,查询方法都放到这里 */
// 获取 name 对应的值。如果为空,则返回空字符串;
value := c.Query("name")
// 获取 name 对应的值,和是否存在 name参数的,ok是 bool 类型
value, ok := c.GetQuery("name")
// 当url中的参数是多选传递时,则需要获取为数组;
// 例如 ?name="张三"&name="Zach"
// 相同的key对应了不同的value,则需要使用这种方式
arr := c.QueryArray("name")
// 作用和 QueryArray 相同,只是多了一个是否有指定key的 返回
arr, ok := c.GetQueryArray("name")
// 当我们按Gin要求的 map 格式传递参数时,则需要获取为map
// 例如 ?ids[a]=1&ids[b]=2&ids[c]=3
// 从以上URL看,关键在于key,这个key必须符合map的定义,[]外面的必须相同,也就是ids这个map变量名,
// []里面的,也就是map的key不能相同,
// 这样就满足了Gin定义的把URL查询参数转换为map的格式定义。
myMap := c.QueryMap("ids")
// 作用和 QueryMap 相同,只是多了一个判断,是否存在对应的key
myMap, ok := c.GetQueryMap("ids")
// 带默认值的获取,如果不存在,则用默认值填充
defaultValue := c. DefaultQuery("name","李四")
获取Form表单参数
通过URL查询参数提交数据到服务器外,常用的还有通过Form表单的方式。Form表单相比URL查询参数,用户体验好,可以承载更多的数据,尤其是文件上传,更是简单。
对于Form表单来说,有两种提交方式GET和POST。其中GET方式就是上面提到的URL查询参数的方式,参考即可获得对应的参数键值对,下面主要介绍POST的方式的表单,而Gin处理的也是这种表单。
Gin 对于表单数据的获取也非常简单,为我们提供了和获取URL查询参数一样的系列方法。
这里需要注意的是保存表单缓存的内存大小,Gin默认给的是32M 如果你觉得不够,可以提前通过修改MaxMultipartMemory的值增加,比如:
r := gin.Default()
r.MaxMultipartMemory = 100 << 20
func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
name := c.PostForm("name")
c.String(200, name)
})
r.Run(":8080")
}
方便整理,查询方法都放到这里
// 获取 key为 name的表单值
value := c.PostForm("name")
// 获取 key为 name的表单值,多了一个ok,确定是否存在对应的key
value, ok := c.GetPostForm("name")
arr := c.PostFormArray("name")
arr, ok := c.GetPostFormArray("name")
myMap := c.PostFormMap("ids")
myMap, ok := c.GetPostFormMap("ids")
defaultValue := c. DefaultPostForm("name","李四")
Url参数获取和Form表单参数获取对比
查询参数 | Form表单 | 说明 |
---|---|---|
Query | PostForm | 获取key对应的值,不存在为空字符串 |
GetQuery | GetPostForm | 多返回一个key是否存在的结果 |
QueryArray | PostFormArray | 获取key对应的数组,不存在返回一个空数组 |
GetQueryArray | GetPostFormArray | 多返回一个key是否存在的结果 |
QueryMap | PostFormMap | 获取key对应的map,不存在返回空map |
GetQueryMap | GetPostFormMap | 多返回一个key是否存在的结果 |
DefaultQuery | DefaultPostForm | key不存在的话,可以指定返回的默认值 |
获取Content-Type: application/json请求头的JSON数据
通过Content-Type: application/json
请求头发送json格式的数据算是最常用了,Gin解析这种方式上传的数据非常方便,一般有两种方法
主要使用 c.BindJSON 方法;查看源码中,还可以解析XML等多种格式。最后都是调用了 c.Bind() 函数
方法一:解析到Map 中
func Login(c *gin.Context) {
json := make(map[string]interface{}) //注意该结构接受的内容
c.BindJSON(&json)
log.Printf("%v",&json)
c.JSON(http.StatusOK, gin.H{
"name": json["name"],
"password": json["password"],
})
}
方法二:直接解析到对应的 struct 对象中
type User struct {
Name string `json:"name"`
Password int64 `json:"password"`
}
func Login(c *gin.Context) {
json := User{}
c.BindJSON(&json)
log.Printf("%v",&json)
c.JSON(http.StatusOK, gin.H{
"name": json.Name,
"password": json.Password,
})
}
获取上传文件
获取上传文件,主要有两个方法, c.FormFile(key)
、c.MultipartForm()
和一个存储文件函数c.SaveUploadedFile(file,path)
单文件上传:c.FormFile(key)
func main() {
router := gin.Default()
// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
// router.MaxMultipartMemory = 8 << 20 // 8 MiB
router.POST("/upload", func(c *gin.Context) {
// 单文件
file, _ := c.FormFile("file")
log.Println(file.Filename)
// 上传文件至指定目录
// c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8080")
}
多文件上传
func main() {
router := gin.Default()
// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
// router.MaxMultipartMemory = 8 << 20 // 8 MiB
router.POST("/upload", func(c *gin.Context) {
// Multipart form
form, _ := c.MultipartForm()
files := form.File["upload[]"]
for _, file := range files {
log.Println(file.Filename)
// 上传文件至指定目录
// c.SaveUploadedFile(file, dst)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
router.Run(":8080")
}