获取Query参数
Query参数又叫Querystring参数,是URL的?后面的一串字符串。
demo代码如下:
r.GET("/home", func(c *gin.Context) {
username := c.Query("username")
password := c.DefaultQuery("password", "******")
addr := c.QueryArray("addr")
class := c.QueryMap("class")
age, ok := c.GetQuery("age")
if ok != true {
fmt.Println(ok)
}
c.JSON(http.StatusOK, gin.H{
"username": username,
"password": password,
"addr": addr,
"class": class,
"age": age,
})
})
结果如下:
![image-20230328201715768](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303282017814.png)
![image-20230328201949671](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303282019717.png)
总结:
Query()用来获取参数
使用DefaultQuery()方法时,如果没有相应的参数,就会使用defaultValue的值来代替。
QueryArray()和QueryMap()方法分别获取切片类型和字典类型的参数
GetQuery()方法返回两个值,一个value,一个bool值。当能够获取到相应的值时,bool值=true;当不能够获取到相应的值时,value为空,bool值=false。
需要注意的是切片类型的参数和字典类型的参数的写法。
- 切片:addr=aaa&addr=bbb
- 字典:class[专业]=软件工程&class[年级]=大一
获取Path参数
Path参数就是路径参数,也就是URL中斜杠和斜杠之间的参数
demo代码如下:
r.GET("/user/info/:username/:password/:hobby", func(c *gin.Context) {
username := c.Param("username")
password := c.Param("password")
hobby := c.Param("hobby")
params := c.Params
c.JSON(http.StatusOK, gin.H{
"username": username,
"password": password,
"hobby": hobby,
"params": params,
})
})
结果如下:
![image-20230328205658430](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303282056482.png)
总结:
把获取的Path参数的前面加上“ : ”,就表示这个Path参数是要获取的参数。
Param()方法只能一个一个的获取参数。
Params()方法是一次性获取所有的Path参数,返回的是Params类型,该类型的定义如下
type Param struct { Key string Value string } type Params []Param
当有一部分Path参数获取不到时,前面获取到的Path参数都会全部丢弃。其本质原因是底层使用rang遍历所有的Path参数,如果没有相应的参数,会把整个params切片置为空。源码如下:
func (ps Params) Get(name string) (string, bool) { for _, entry := range ps { if entry.Key == name { return entry.Value, true } } return "", false //注意:并不是将entry.Value置为nil,而是将整个切片置为空。 } func (ps Params) ByName(name string) (va string) { va, _ = ps.Get(name) return } func (c *Context) Param(key string) string { return c.Params.ByName(key) }
获取Form表单参数
Demo代码如下:
r.POST("/info", func(c *gin.Context) {
username := c.PostForm("username")
password := c.DefaultPostForm("password", "******")
hobby := c.PostFormArray("hobby")
sex, ok := c.GetPostForm("sex")
if ok != true {
fmt.Println(ok)
}
c.JSON(http.StatusOK, gin.H{
"username": username,
"password": password,
"sex": sex,
"hobby": hobby,
})
})
结果如下:
![image-20230329140639480](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303291406615.png)
![image-20230329140320814](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303291403064.png)
总结:
- PostForm()方法获取表单参数
- 使用DefaultPostForm()方法如果没有获取到参数,会有默认值代替
- PostFormArray()获取数组对象的表单参数
- GetPostForm()方法返回两个值,第一个是表单参数,第二个是bool值
获取Json参数
Demo代码如下:
r.POST("/json", func(c *gin.Context) {
var m map[string]interface{}
body, err := c.GetRawData() //从请求体(body)中获取json数据
if err != nil {
fmt.Println(err.Error())
}
err = json.Unmarshal(body, &m)
if err != nil {
fmt.Println(err.Error())
}
name := m["name"]
email := m["email"]
c.JSON(http.StatusOK, gin.H{
"name": name,
"email": email,
})
})
结果如下:
![image-20230329163925637](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303291639767.png)
总结:
GetRawData()方法是从请求体(body)中获取原始的json数据
GetRawData()底层使用ioutil包里面的ReadAll()方法来读取数据,ReadAll()方法底层使用io包里面的ReadAll()函数,ReadAll()函数的源码如下:
func ReadAll(r Reader) ([]byte, error) { b := make([]byte, 0, 512) for { if len(b) == cap(b) { // Add more capacity (let append pick how much). b = append(b, 0)[:len(b)] } n, err := r.Read(b[len(b):cap(b)]) b = b[:len(b)+n] if err != nil { if err == EOF { err = nil } return b, err } } }
源码分析可以看这篇文章:
获取请求头中的数据
Demo代码如下:
r.GET("/header", func(c *gin.Context) {
token := c.GetHeader("Authorization")
c.JSON(http.StatusOK, gin.H{
"Authorization": token,
})
})
结果如下:
![image-20230329165517194](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303291655305.png)
总结:
- GetHeader()方法用于获取请求头信息
- 设置请求头的方法有两种:
- c.Header(“Authorization”, “xxx.yyy.zzz”)
- c.Writer.Header().Set(“Authorization”, “xxx.yyy.zzz”)
数据绑定
基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了BindJSON()和ShouldBindJSON,它能够基于请求自动提取JSON类型的数据,并把值绑定到指定的结构体对象。
Demo代码如下:
type Login struct {
Username string `json:"username"`
Password string `json:"password"`
}
r.GET("/bindJson", func(c *gin.Context) {
var login Login
err := c.BindJSON(&login)
if err != nil {
fmt.Println(err.Error())
}
username := login.Username
password := login.Password
c.JSON(http.StatusOK, Login{
Username: username,
Password: password,
},
)
})
r.GET("/shouldBindJson", func(c *gin.Context) {
var login Login
err := c.ShouldBindJSON(&login)
if err != nil {
fmt.Println(err.Error())
}
username := login.Username
password := login.Password
c.JSON(http.StatusOK, Login{
Username: username,
Password: password,
},
)
})
结果如下:
![image-20230329183020139](https://liubing-1314895948.cos.ap-chengdu.myqcloud.com/img/202303291830227.png)
总结:
数据绑定是利用结构体的反射机制来实现的,只要结构体里面有相应的Tag标签,就能实现对应数据类型的绑定。
ShouldBindxxx和Bindxxx区别:如果Bindxxx没有绑定到数据,会在Header中添加400的返回信息,而ShouldBindxxx不会。验证结果如下:
![]()