原创做者,公众号【程序员读书】,欢迎关注公众号,转载文章请注明出处哦。html
前面写了两篇与Gin
框架学习有关的文章,主要讲了Gin
框架的安装,定义处理HTTP
请求的各类方法以及如何根据客户端需求返回不一样格式的数据,但这中间漏了一个环节,那就是返回数据以前,如何获取客户端HTTP
请求中带上来的参数,关于这点,咱们就在这篇文章中讲一讲。程序员
Gin
框架将处理HTTP
请求参数以及如何响应等操做都封装到了gin.Conetxt
结构体,并为gin.Context
提供了很是多的方法,所以了解gin.Context
的结构定义与方法,对使用Gin
框架编写Web
项目很是重要。json
下面是gin.Context
结构定义代码:数组
type Context struct {
Request *http.Request
Writer ResponseWriter
Params Params
// Keys is a key/value pair exclusively for the context of each request.
Keys map[string]interface{}
// Errors is a list of errors attached to all the handlers/middlewares who used this context.
Errors errorMsgs
// Accepted defines a list of manually accepted formats for content negotiation.
Accepted []string
// contains filtered or unexported fields
}
复制代码
从上面的gin.Context
的结构定义来看,gin.Context
封装了http.Request
和http.ResponseWriter
安全
path是指请求的url中域名以后从/开始的部分,如掘金首页地址:https://juejin.im/timeline
,/timeline
部分即是path,可使用gin.Context中的Param()方法获取这部分参数。bash
func (c *Context) Param(key string) string
复制代码
使用Param()方法获取path中的参数:服务器
r.GET("/user/:id",func(c *gin.Context){
id := c.Param("id")
})
复制代码
除了使用gin.Context的中Param()方法外,还能够用gin.Context中的Params字段获取到path中的参数,Params的定义以下:数据结构
type Params []Param
func (ps Params) ByName(name string) (va string)
func (ps Params) Get(name string) (string, bool)
复制代码
使用gin.Context中的Params字段获取path中的参数示例以下:app
r.GET("/user/:id",func(c *gin.Context){
id,err := c.Params.Get("id")
//id := c.Params.ByName("id")
})
复制代码
query是指url请求地址中的问号后面的部,称为查询参数,以下面地址中,query=%E6%96%87%E7%AB%A0&type=all
就是查询参数。框架
https://juejin.im/search?query=%E6%96%87%E7%AB%A0&type=all
复制代码
gin.Context
提供了如下几个方法,用于获取Query部分的参数。
func (c *Context) GetQuery(key string) (string, bool)
func (c *Context) Query(key string) string
func (c *Context) DefaultQuery(key, defaultValue string) string
复制代码
上面三个方法用于获取单个数值,GetQuery
比Query
多返回一个error类型的参数,实际上Query
方法只是封装了GetQuery
方法,并忽略GetQuery
方法返回的错误而已,而DefaultQuery方法则在没有获取相应参数值的返回一个默认值。
示例以下:
r.GET("/user", func(c *gin.Context) {
id,_ := c.GetQuery("id")
//id := c.Query("id")
//id := c.DefaultQuery("id","10")
c.JSON(200,id)
})
复制代码
请求:http://localhost:8080/user?id=11
响应:11
GetQueryArray方法和QueryArray的区别与GetQuery和Query的类似。
func (c *Context) GetQueryArray(key string) ([]string, bool)
func (c *Context) QueryArray(key string) []string
复制代码
示例以下:
r.GET("/user", func(c *gin.Context) {
ids := c.QueryArray("id")
//id,_ := c.QueryArray("id")
c.JSON(200,ids)
})
复制代码
请求:http://localhost:8080/user?id=10&id=11&id=12
响应:["10","11","12"]
GetQueryArray方法和QueryArray的区别与GetQuery和Query的类似。
func (c *Context) QueryMap(key string) map[string]string
func (c *Context) GetQueryMap(key string) (map[string]string, bool)
复制代码
示例以下:
r.GET("/user", func(c *gin.Context) {
ids := c.QueryMap("ids")
//ids,_ := c.GetQueryMap("ids")
c.JSON(200,ids)
})
复制代码
请求:http://localhost:8080/user?ids[10]=zhang
响应:{"10":"zhang"}
通常HTTP的Post请求参数都是经过body部分传给服务器端的,尤为是数据量大或安全性要求较高的数据,如登陆功能中的帐号密码等参数。
gin.Context提供了如下四个方法让咱们获取body中的数据,不过要说明的是,下面的四个方法,只能获取Content-type
是application/x-www-form-urlencoded
或multipart/form-data
时body
中的数据。
下面方法的使用方式与上面获取Query的方法使用类型,区别只是数据来源不一样而已,这里便再也不写示例程序。
func (c *Context) PostForm(key string) string
func (c *Context) PostFormArray(key string) []string
func (c *Context) PostFormMap(key string) map[string]string
func (c *Context) DefaultPostForm(key, defaultValue string) string
func (c *Context) GetPostForm(key string) (string, bool)
func (c *Context) GetPostFormArray(key string) ([]string, bool)
func (c *Context) GetPostFormMap(key string) (map[string]string, bool)
func (c *Context) GetRawData() ([]byte, error)
复制代码
在前面的例子中,咱们直接使用gin.Context
提供的方法获取请求中经过path
、query
、body
带上来的参数,但使用前面的那些方法,并不能处理请求中比较复杂的数据结构,好比Content-type为application/json或application/xml时,其所带上的数据会很复杂,所以咱们须要使用另一种方法获取这些数据,这种方式叫数据绑定
。
Gin
框架将数据绑定的操做都封装在gin/binding这个包中,下面是gin/binding包
定义的常量,说明gin/binding
包所支持的Content-type
格式。
const (
MIMEJSON = "application/json"
MIMEHTML = "text/html"
MIMEXML = "application/xml"
MIMEXML2 = "text/xml"
MIMEPlain = "text/plain"
MIMEPOSTForm = "application/x-www-form-urlencoded"
MIMEMultipartPOSTForm = "multipart/form-data"
MIMEPROTOBUF = "application/x-protobuf"
MIMEMSGPACK = "application/x-msgpack"
MIMEMSGPACK2 = "application/msgpack"
MIMEYAML = "application/x-yaml"
)
复制代码
gin.binding
包也定义处理不一样Content-type
提交数据的处理结构体,并以变量的形式让其余包能够访问,以下:
var (
JSON = jsonBinding{}
XML = xmlBinding{}
Form = formBinding{}
Query = queryBinding{}
FormPost = formPostBinding{}
FormMultipart = formMultipartBinding{}
ProtoBuf = protobufBinding{}
MsgPack = msgpackBinding{}
YAML = yamlBinding{}
Uri = uriBinding{}
)
复制代码
但实际上,咱们并不须要调用gin/binding
包的代码来完成数据绑定的功能,由于gin.Context
中已经在gin.Context
的基础上封装了许多更加快捷的方法供咱们使用:
gin.Context
封装的相关绑定方法,分为以Bind
为前缀的系列方法和以ShouldBind
为前缀的系列方法,这两个系列方法之间的差异在于以Bind为前缀的方法,在用户输入数据不符合相应格式时,会直接返回http状态为400的响应给客户端。
func (c *Context) BindUri(obj interface{}) error
复制代码
代码示例:
type User struct {
Uid int //用户id
Username string //用户名
}
func main() {
r := gin.Default()
r.GET("/bind/:uid/username", func(c *gin.Context) {
var u User
e := c.BindUri(&u)
if e == nil{
c.JSON(200,u)
}
})
r.Run()
}
复制代码
请求:http://localhost:8080/bind/1/小张
输入:{1,"小张"}
func (c *Context) BindQuery(obj interface{}) error
复制代码
代码示例:
r.GET("/bind/:uid/username", func(c *gin.Context) {
var u User
e := c.BindQuery(&u)
if e == nil{
c.JSON(200,u)
}
})
复制代码
请求:http://localhost:8080/bind?uid=1&username=小张
输出:{1,"小张"}
当咱们在HTTP
请求中Body
设置不一样数据格式,须要设置相应头部Content-Type
的值,比较经常使用为json
、xml
、yaml
,gin.Context
提供下面三个方法绑定对应Content-type时body中的数据。
func (c *Context) BindJSON(obj interface{}) error
func (c *Context) BindXML(obj interface{}) error
func (c *Context) BindYAML(obj interface{}) error
复制代码
除了上面三个方法外,更经常使用的Bind()方法,Bind()方法会自动根据Content-Type的值选择不一样的绑定类型。
func (c *Context) Bind(obj interface{}) error
复制代码
示例
r.POST("bind",func(c *gin.Context){
u := User{}
c.Bind(&u)
})
复制代码
上面几个方法都是获取固定Content-type或自动根据Content-type选择绑定类型,咱们也可使用下面两个方法自行选择绑定类型。
下面两个方法的第二个参数值是gin.binding中定义好的常量,咱们在上面讲过。
func (c *Context) BindWith(obj interface{}, b binding.Binding) error
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error
复制代码
示例
r.POST("bind",func(c *gin.Context){
u := User{}
c.BindWith(&u,binding.JSON)
c.MustBindWith(&u,binding.JSON)
})
复制代码
以ShouldBind为前缀的相应的方法与以Bind为前缀的方法使用基本相同,所以下面没有相应演示的代码。
func (c *Context) ShouldBindUri(obj interface{}) error
复制代码
func (c *Context) ShouldBindQuery(obj interface{}) error
复制代码
func (c *Context) ShouldBind(obj interface{}) error
func (c *Context) ShouldBindJSON(obj interface{}) error
func (c *Context) ShouldBindXML(obj interface{}) error
func (c *Context) ShouldBindYAML(obj interface{}) error
func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error)
func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error
复制代码
Gin
框架在net/http
包的基础上封装了许多的方法,让咱们能够接收客户端传递上来的各类不一样格式的数据,可是从客户端获得的数据以后,仍是要验证数据是否合法或是否咱们想要的,这是Gin
框架中有关数据验证器
的知识了,有机会再写写这方面的文章。
你的关注,是我写做路上最大的鼓励!