网站首页 > 技术教程 正文
1 介绍
Gin中可以方便的获取URL中的查询参数,或者也可以简称为URL参数,此类参数以?为起点,后面的k=v&k1=v1&k2=v2这样的字符串就是查询参数,本小节通过示例演示获取URL查询参数的方式,以及背后的实现方式。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// GET请求 url ?后面是querystring参数,key = value格式,多个key-value用&连接
// eg: /queryParams?name=randySun&age=18
r.GET("/queryParams", func(c *gin.Context) {
name := c.Query("name")
age := c.Query("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.GET("/queryDefault", func(c *gin.Context) {
name := c.DefaultQuery("name", "body")
age := c.DefaultQuery("age", "18")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.GET("/queryGet", func(c *gin.Context) {
name, ok := c.GetQuery("name")
if !ok {
name = "body"
}
age, ok := c.GetQuery("age")
if !ok {
age = "18"
}
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.Run(":9999")
}
有三种获取URL查询参数的方式,分别是Query、DefaultQuery和GetQuery。其中最基本的是Query,针对上面的例子,使用curl测试如下。
curl "127.0.0.1:9999/queryParams?name=TerryPro&age=10 "
{"age":"10","name":"TerryPro"}
2 Query分析
// Query returns the keyed url query value if it exists,
// otherwise it returns an empty string `("")`.
// It is shortcut for `c.Request.URL.Query().Get(key)`
// GET /path?id=1234&name=Manu&value=
// c.Query("id") == "1234"
// c.Query("name") == "Manu"
// c.Query("value") == ""
// c.Query("wtf") == ""
func (c *Context) Query(key string) string {
value, _ := c.GetQuery(key)
return value
}
通过注释可以看出,Query返回参数值,如果不存在的话则返回空字符串""。在内部使用GetQuery获取具体的参数值。
3 GetQuery分析
// GetQuery is like Query(), it returns the keyed url query value
// if it exists `(value, true)` (even when the value is an empty string),
// otherwise it returns `("", false)`.
// It is shortcut for `c.Request.URL.Query().Get(key)`
// GET /?name=Manu&lastname=
// ("Manu", true) == c.GetQuery("name")
// ("", false) == c.GetQuery("id")
// ("", true) == c.GetQuery("lastname")
func (c *Context) GetQuery(key string) (string, bool) {
if values, ok := c.GetQueryArray(key); ok {
return values[0], ok
}
return "", false
}
GetQuery内部调用GetQueryArray获取URL查询参数的值,如果查询参数存在的话,则返回(value,true),如果参数值存在但是没有设置值,则返回("", true),见注释中的lastname;如果不存在的话则返回("",false)。GetQueryArray实际上返回的是数组,后面会详细分析。GetQuery仅返回第一个就行。
4 GetQueryArray分析
// GetQueryArray returns a slice of strings for a given query key, plus
// a boolean value whether at least one value exists for the given key.
func (c *Context) GetQueryArray(key string) ([]string, bool) {
c.initQueryCache()
if values, ok := c.queryCache[key]; ok && len(values) > 0 {
return values, true
}
return []string{}, false
}
func (c *Context) initQueryCache() {
if c.queryCache == nil {
if c.Request != nil {
c.queryCache = c.Request.URL.Query()
} else {
c.queryCache = url.Values{}
}
}
}
type Values map[string][]string
type Context struct {
// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
queryCache url.Values
}
(1)首次调用initQueryCache获取查询参数,由于在一个请求中可能会多次调用Query方法因此使用Context中的queryCache对Query参数进行了缓存。
(2)通过源码可以看出,queryCache的类型是一个键类型为字符串,值类型是字符串切片。
(3)initQueryCache调用URL的Query方法对URL进行解析。
5 GetQuery分析
// DefaultQuery returns the keyed url query value if it exists,
// otherwise it returns the specified defaultValue string.
// See: Query() and GetQuery() for further information.
// GET /?name=Manu&lastname=
// c.DefaultQuery("name", "unknown") == "Manu"
// c.DefaultQuery("id", "none") == "none"
// c.DefaultQuery("lastname", "none") == ""
func (c *Context) DefaultQuery(key, defaultValue string) string {
if value, ok := c.GetQuery(key); ok {
return value
}
return defaultValue
}
GetQuery和Query的区别是,如果没有查询到相应的参数则直接返回传入的参数defaultValue。
6 查询数组
从上面的分析可以看出Gin还提供了QueryArray和GetQueryArray两种方法能够获取URL中的数组,例子如下:
r.GET("/queryArray", func(c *gin.Context) {
name := c.QueryArray("name")
c.JSON(http.StatusOK, gin.H{
"name": name,
})
})
curl "http://127.0.0.1:9999/queryArray?name=TerryPro&name=Hexiaoyu"
{"name":["TerryPro","Hexiaoyu"]}
可以看出当URL中存在多个重复的参数时,调用QueryArray时可以返回一个数组切片。第4节对GetQueryArray进行了分析,下面对QueryArray进行简单的分析。
7 QueryArray分析
// QueryArray returns a slice of strings for a given query key.
// The length of the slice depends on the number of params with the given key.
func (c *Context) QueryArray(key string) []string {
values, _ := c.GetQueryArray(key)
return values
}
QueryArray在内部调用GetQueryArray,如果不存在待查询的参数,则返回[]string{}。
8 QueryMap
Context中还提供了2个函数QueryMap、GetQueryMap,用于将Query参数转化成map的形式,这两个函数处理的URL查询参数形式为:?params[key1]=value1¶ms[key2]=value2¶ms[key3]=value3,下面举个例子,同时对相应的源码进行分析。
r.GET("/queryMap", func(c *gin.Context) {
params := c.QueryMap("params")
c.JSON(http.StatusOK, gin.H{
"params": params,
})
})
使用如下命令进行测试。
curl "127.0.0.1:9999/queryMap?params\[key1\]=value1?ms\[key2\]=value2?ms\[key3\]=value3"
{"params":{"key1":"value1","key2":"value2","key3":"value3"}}
注意在curl命令中发送多个参数使用"",并且需要对[]进行转移处理。下面对QueryMap和GetQueryMap函数进行分析。
// QueryMap returns a map for a given query key.
func (c *Context) QueryMap(key string) map[string]string {
dicts, _ := c.GetQueryMap(key)
return dicts
}
// GetQueryMap returns a map for a given query key, plus a boolean value
// whether at least one value exists for the given key.
func (c *Context) GetQueryMap(key string) (map[string]string, bool) {
// 缓存参数到queryCache中,然后对参数进行解析
c.initQueryCache()
return c.get(c.queryCache, key)
}
// get is an internal method and returns a map which satisfy conditions.
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
}
(1)QueryMap内部调用GetQueryMap,GetQueryMap返回一个map[string]string的参数值和一个是否成功的标识;首先仍然解析查询参数并缓存到queryCache中,调用一个内部的get从queryCache中获取map参数;
(2)get函数看起来比较复杂,实际上是一个解析方法,针对每一个参数,将其分解为key、'['、mapkey、']'四个部分,比如上面的params[key1]就被分解为params、'['、 key1、 ']'四个字段,匹配params成功后,则在dicts中创建一个字段,dicts[key1] = value1。
9 小节
在Gin中接收数组是比较常用的,但是map不常用。其实对于接收参数来说,不光我们可以从URL查询参数中获得,还可以从提交的表单(Form)中获得,它们的原理是大同小异的,使用方式也非常像,下一篇就介绍表单的使用和原理分析。
猜你喜欢
- 2024-11-13 利用query 实现多条件判断 query多条件查询
- 2024-11-13 百万到亿级数据,快速统计查询 百万数据查询解决方案
- 2024-11-13 TXT在Excel里还能这么用?一键导入、分列都不在话下
- 2024-11-13 数据分析选它,轻松搞定数据可视化
- 2024-11-13 BAT大厂员工都懂的Excel Power Query,你还不了解吗?
- 2024-11-13 EXCEL实用Power/Query功能应用,快捷提取中英文,无视内容格式
- 2024-11-13 7 款常用的 PostgreSQL GUI 工具测评
- 2024-11-13 网站验证说明 网络网页验证
- 2024-11-13 Python 闲谈 17——阿里巴巴开发中DO,DTO,VO,Query,AO的区别
- 2024-11-13 2022年高考成绩查询 2022年高考成绩查询官网
你 发表评论:
欢迎- 05-23不用羡慕Mac,Windows电脑可以直接访问iPhone相册了
- 05-23换了电脑上不去网怎么回事?看看如何修改mac地址!
- 05-23怎么查看打印机IP地址
- 05-23查看电脑端口号的方法
- 05-23怎么查电脑局域网中的其他电脑ip地址
- 05-23如何查看笔记本电脑尺寸
- 05-23【网络】IP地址冲突如何快速定位?
- 05-23电脑系统改mac地址的方法
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)