11

Golang Gin 实战(五):接收数组和 Map

 4 years ago
source link: https://mp.weixin.qq.com/s/u4R5MZABcy-231g4_HDrdg
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在 上一篇 Golang Gin 实战(四)| URL查询参数的获取和原理分析 文章中,因为文章篇幅问题, QueryArrayQueryMap 没有介绍,这篇文章继续。

QueryArray

在实际的业务开发中,我们有些业务多选的,比如一个活动有多个人参加,一个问题有多个答案等等,对于这类业务功能来说,如果是通过查询参数提交的,它们的URL大概这样 ?a=b&a=c&a=d , key 值都一样,但是对应的 value 不一样。

这类URL查询参数,就是一个数组,那么在Gin中我们如何获取它们呢?

这里举个例子,比如有一份调查问卷,问我有哪些自媒体,我选择个人博客和微信公众号

func main() {
r := gin.Default()

r.GET("/", func(c *gin.Context) {
c.JSON(200, c.QueryArray("media"))
})
r.Run(":8080")
}

运行代码,在浏览器里访问 http://localhost:8080/?media=blog&media=wechat ,会看到如下信息:

["blog","wechat"]

我们的自媒体信息,已经作为一个数组被输出了,非常简单,这样我们就可以很方便的处理多选的业务。

QueryArray 方法也有对应的 GetQueryArray 方法,区别在于返回对应的 key 是否存在,这里不再举例。

QueryArrayGetQueryArray 源代码实现已经在上一篇  Golang Gin 实战(四)| URL查询参数的获取和原理分析 分析了,这里不再赘述,大家可以再看下上一篇文章。

QueryMap

QueryMap 其实就是把满足一定格式的URL查询参数,转换为一个 map ,假设有a,b,c三个人,他们对应的id是123,456,789.那么用map的方式表示,这种格式类似于:

?ids[a]=123&ids[b]=456&ids[c]=789

从以上URL看,关键在于 key ,这个key必须符合 map 的定义, [] 外面的必须相同,也就是 ids 这个 map 变量名, [] 里面的,也就是 map 的key不能相同,这样就满足了 Gin 定义的把URL查询参数转换为 map 的格式定义。

    r.GET("/map", func(c *gin.Context) {
c.JSON(200, c.QueryMap("ids"))
})

获取 map 的方法很简单,把 ids 作为 key 即可。现在运行代码,访问 http://localhost:8080/map?ids[a]=123&ids[b]=456&ids[c]=789 ,就会看到如下信息:

{"a":"123","b":"456","c":"789"}

我们输入的信息,正好被我们打印出来了。

GetQueryMapQueryMap 是一样的,只是返回了对应的 key 是否存在。

QueryMap 的原理

func (c *Context) QueryMap(key string) map[string]string {
dicts, _ := c.GetQueryMap(key)
return dicts
}

func (c *Context) GetQueryMap(key string) (map[string]string, bool) {
c.getQueryCache()
return c.get(c.queryCache, key)
}

QueryMap 是通过 GetQueryMap ,最终都是 c.get 这个方法实现,我们只需要分析 c.get 就可以了。注意这里同样用到了 getQueryCache 进行缓存提高性能。

func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) {
dicts := make(map[string]string)
exist := false
for k, v := range m {
if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
exist = true
dicts[k[i+1:][:j]] = v[0]
}
}
}
return dicts, exist
}

这段实现代码看着比较绕,其实挺简单,它有两个参数,一个 m 其实就是缓存的所有查询参数键值对 queryCache ,另外一个就是我们要找的 key

因为 Gin 定义的map的URL特殊格式化,所以这里需要判断是否有 [] ,如果有的话,并且 key 匹配,那么这个键值对就是我们需要找的,把它存在 dicts 即可,最终返回的是这个 dicts

这里等于是, Gin 帮我们做了包装,可以更好的把特殊格式的URL转为 map ,提升了我们使用的效率,不过这种方法不常用,如果有特别的需要可以使用。

小结

接收数组是比较常用的,但是 map 不常用。其实对于接收参数来说,不光我们可以从URL查询参数中获得,还可以从提交的表单(Form)中获得,它们的原理是大同小异的,使用方式也非常像,下一篇我们就介绍表单的使用和原理分析。

感谢新老朋友的转发、阅读和点赞支持,给大家抽个现金红包(点击参与),在看到50,下次抽奖金额翻倍!

我有几个的Go语言交流微信群,可以扫码关注公众号 flysnow_org 或者网站 https://www.flysnow.org/,加我好友,我拉你进来。

往期 精彩 回顾

Golang Gin 实战(四)| URL查询参数的获取和原理分析

Golang Gin 实战(三)| 路由参数

Golang Gin 实战(二)| 简便的Restful API 实现

Golang Gin 实战(一)| 快速安装入门

7JNjUfq.jpg!web

扫码关注


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK