在 上一篇 Golang Gin 实战(三)| 路由参数 文章中,主要介绍了路由通配符、路由参数,让我们有了一种可以从URL路径中获取参数的方式,同时又不是重复的注册相似的路由。
这一篇,主要介绍查询参数,以及获取查询参数的示例以及底层原理。
Querystring parameters ,翻译成中文我只能叫查询参数了,不过觉得挺别捏的。其实这种参数我们并不陌生,比如:
https://www.flysnow.org/search?q=golang&sitesearch=https%3A%2F%2Fwww.flysnow.org
URL查询参数,或者也可以简称为URL参数,是存在于我们请求的URL中,以?
为起点,后面的k=v&k1=v1&k2=v2
这样的字符串就是查询参数,比如我上面示例中的:
?q=golang&sitesearch=https%3A%2F%2Fwww.flysnow.org
这个示例中有两个查询参数键值对:
q=golang
sitesearch=https%3A%2F%2Fwww.flysnow.org
第一个key是q
,对应的值是golang
。第二个key是sitesearch
,对应的值是https%3A%2F%2Fwww.flysnow.org
,它们通过&
相连。在URL中,多个查询参数键值对通过&
相连。
在Gin
中,为我们提供了简便的方法来获取查询参数的值,我们只需要知道查询参数的key(参数名)就可以了。
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(200, c.Query("wechat"))
})
r.Run(":8080")
}
我们运行这段代码,打开浏览器访问http://localhost:8080/?wechat=flysnow_org
,就可以看到flysnow_org
文字。这表示我们通过c.Query("wechat")
获取到了查询参数wechat
的值是flysnow_org
。
Query
方法为我们提供了获取对应key
的值的能力,如果该key
不存在,则返回""
字符串。如果对于一些数字参数,比如id
如果返回为空的话,我们进行字符串转数字的时候会报错,这时候,我们就可以通过DefaultQuery
方法指定一个默认值:
c.DefaultQuery("wechat", "flysnow_org")
c.DefaultQuery("id", "0")
比如这样,尤其是第二个例子,默认为0,让我们字符串转数字很方便。
func (c *Context) Query(key string) string {
value, _ := c.GetQuery(key)
return value
}
func (c *Context) DefaultQuery(key, defaultValue string) string {
if value, ok := c.GetQuery(key); ok {
return value
}
return defaultValue
}
看下这两个函数的源代码实现,它们都是调用的GetQuery
方法获取对应的值,唯一不同的是DefaultQuery
会判断对应的key
是否存在,如果不存在的话,则返回默认defaultValue
值。
从以上两个获取查询参数值的方法可以看到,他们调用的都是GetQuery
,这也是gin.Context
的一个方法,它和Query
唯一不同的是,它返回两个值,可以告诉我们要获取的key
是否存在。
value, ok := c.GetQuery("wechat")
如果我们自己的业务中,需要这类功能,可以用GetQuery
来代替Query
方法。
GetQuery
方法的底层实现其实是c.Request.URL.Query().Get(key)
,通过url.URL.Query()
来获取所有的参数键值对。
本质上是调用的GetQueryArray,取的数组中第一个值
func (c *Context) GetQuery(key string) (string, bool) {
if values, ok := c.GetQueryArray(key); ok {
return values[0], ok
}
return "", false
}
func (c *Context) GetQueryArray(key string) ([]string, bool) {
c.getQueryCache() //缓存所有的键值对
if values, ok := c.queryCache[key]; ok && len(values) > 0 {
return values, true
}
return []string{}, false
}
func (c *Context) getQueryCache() {
if c.queryCache == nil {
c.queryCache = c.Request.URL.Query()
}
}
从以上的实现代码中,可以看到最终的实现都在GetQueryArray
方法中,找到对应的key
就返回对应的[]string
,返回就返回空数组。
这里Gin
进行了优化,通过缓存所有的键值对,提升代码的查询效率。这里缓存的queryCache
本质上是url.Values
,也是一个map[string][]string
。
type Values map[string][]string
其中c.Request.URL.Query()
这个方法就是把?k=v&k1=v1&k2=v2
这类查询键值对转换为map[string][]string
,所以还是很耗性能的,这里Gin
采用了缓存的做法提高了性能挺好,这也是Gin
成为性能最快的Golang Web 框架的原因之一吧。
在原理分析这一小结,相信大家也看到了GetQueryArray
函数,可以让我们获取key
对应的数组,比如多选这类功能,本来打算这一篇文章就介绍下呢,发现这篇内容已经不少了,太多了,大家不容易看完,所以就放到下一节吧。
可能大家没有留意,我的文章,我都会稍微加入一些原理、源代码的分析,这个主要就是为了让大家更了解其中的原理,可以更好的使用它们,更为了大家能够通过这个分析,提升自己的技术能力,比如这里用到的缓存机制。
感谢新老朋友的转发、阅读和点赞支持,给大家抽个现金红包(点击参与),在看到50,下次抽奖金额翻倍!
我有几个的Go语言交流微信群,可以扫码关注公众号flysnow_org
或者网站 https://www.flysnow.org/,加我好友,我拉你进来。
往期精彩回顾
Golang Gin 实战(三)| 路由参数
Golang Gin 实战(二)| 简便的Restful API 实现
Golang Gin 实战(一)| 快速安装入门
扫码关注