原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。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
框架中有關數據驗證器
的知識了,有機會再寫寫這方面的文章。
你的關注,是我寫做路上最大的鼓勵!