這篇文章主要講解了“Golang GinWeb之怎么請求參數(shù)綁定和驗(yàn)證”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Golang GinWeb之怎么請求參數(shù)綁定和驗(yàn)證”吧!
創(chuàng)新互聯(lián)建站于2013年開始,先為江門等服務(wù)建站,江門等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為江門企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
模型綁定和驗(yàn)證
使用模型綁定來綁定請求體到一個(gè)Go類型上. 目前支持JSON,XML,YAML以及標(biāo)準(zhǔn)表單(如foo=bar&boo=baz)的綁定.
Gin使用go-playground/validator/v10包來驗(yàn)證請求, 關(guān)于tags在驗(yàn)證中使用詳見(https://godoc.org/github.com/go-playground/validator#hdr-Baked_In_Validators_and_Tags)
注意:綁定前請確認(rèn)結(jié)構(gòu)體中需要綁定的字段標(biāo)簽與綁定類型一致,比如綁定JSON,設(shè)置標(biāo)簽: json:"fieldname"
Gin提供兩種方式(類型)來完成綁定:
Must bind
1. 方法: Bind, BindJSON, BindXML, BindQuery, BindYAML, BindHeader
2. 特點(diǎn): 這些方法底層使用MustBindWith方法. 如果出現(xiàn)綁定錯(cuò)誤, 請求將以狀態(tài)碼400返回失敗信息:c.AbortWithError(400, err).SetType(ErrorTypeBind), 響應(yīng)中設(shè)置Content-Type頭為text/plain; charset=utf-8.如果手動(dòng)設(shè)置響應(yīng)碼,會警告響應(yīng)頭已經(jīng)設(shè)置,比如提示: [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422, 如果想要更好的控制這些行為,建議使用下面對應(yīng)的ShoudBind方法.
Should bind
1. 方法: ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML, ShouldBindHeader
2. 特點(diǎn): 這些方法底層使用ShouldBindWith. 如果出現(xiàn)綁定錯(cuò)誤, 會返回錯(cuò)誤, 開發(fā)者可以控制和恰當(dāng)?shù)奶幚磉@些錯(cuò)誤.
當(dāng)使用綁定方法時(shí), Gin嘗試根據(jù)類型頭Content-Type header自動(dòng)推斷要使用的綁定器. 如果你已經(jīng)確認(rèn)需要綁定的類型,可以直接使用底層的MustBindWith或ShouldBindWith方法.
你也可以針對特殊的字段指定required標(biāo)簽值, 如果某個(gè)字段指定了:binding:"required"標(biāo)簽, 但是在綁定時(shí)該字段為空會返回錯(cuò)誤.
如以下代碼綁定JSON:
package main import ( "github.com/gin-gonic/gin" "net/http" ) // Binding from JSON type Login struct { User string `form:"user" json:"user" xml:"user" binding:"required"` //分別定義form,json,xml,binding等標(biāo)簽 //Password string `form:"password" json:"password" xml:"password" binding:"required"` Password string `form:"password" json:"password" xml:"password" binding:"-"` } func main() { router := gin.Default() // Example for binding JSON ({"user": "manu", "password": "123"}) router.POST("/loginJSON", func(c *gin.Context) { var json Login if err := c.ShouldBindJSON(&json); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if json.User != "manu" || json.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) }) // Example for binding XML ( // <?xml version="1.0" encoding="UTF-8"?> // <root> // <user>user</user> // <password>123</password> // </root>) router.POST("/loginXML", func(c *gin.Context) { var xml Login if err := c.ShouldBindXML(&xml); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if xml.User != "manu" || xml.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) }) // Example for binding a HTML form (user=manu&password=123) router.POST("/loginForm", func(c *gin.Context) { var form Login // This will infer what binder to use depending on the content-type header. if err := c.ShouldBind(&form); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if form.User != "manu" || form.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) }) // Listen and serve on 0.0.0.0:8080 router.Run(":8080") } //模擬請求: curl -v -X POST http://localhost:8080/loginJSON -H 'content-type: application/json' -d '{ "user": "manu", "password": "123" }'
跳過驗(yàn)證: 與binding:"required"標(biāo)簽對應(yīng)的是binding:"-", 表示該字段不做綁定, 所以綁定時(shí)該字段為空不會報(bào)錯(cuò).
自定義驗(yàn)證器
你也可以自己注冊一個(gè)自定義驗(yàn)證器, 示例代碼請參考(https://github.com/gin-gonic/examples/blob/master/custom-validation/server.go)
package main import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" ) // Booking contains binded and validated data. // Booking結(jié)構(gòu)中定義了包含綁定器和日期驗(yàn)證器標(biāo)簽 type Booking struct { CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"` //登記時(shí)間 CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"` //gtfield=CheckIn表示結(jié)賬時(shí)間必須大于登記時(shí)間 } // 定義日期驗(yàn)證器 var bookableDate validator.Func = func(fl validator.FieldLevel) bool { date, ok := fl.Field().Interface().(time.Time) //利用反射獲取到字段值 -> 轉(zhuǎn)為接口 -> 類型斷言(時(shí)間類型) if ok { today := time.Now() if today.After(date) { //如果當(dāng)前時(shí)間在checkIn字段時(shí)間之后,返回false,即登記時(shí)間不能早于當(dāng)前的時(shí)間 return false } } return true } func main() { route := gin.Default() //對binding.Validator.Engine()接口進(jìn)行類型斷言,斷言類型為Validate結(jié)構(gòu),如果斷言成功,就將自定義的驗(yàn)證器注冊到Gin內(nèi)部 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { // - if the key already exists, the previous validation function will be replaced. 該注冊方法會將已經(jīng)存在的驗(yàn)證器替換 // - this method is not thread-safe it is intended that these all be registered prior to any validation // 注冊方法不是線程安全的, 在驗(yàn)證開始前,需要保證所有的驗(yàn)證器都注冊成功 v.RegisterValidation("bookabledate", bookableDate) } route.GET("/bookable", getBookable) route.Run(":8085") } func getBookable(c *gin.Context) { var b Booking if err := c.ShouldBindWith(&b, binding.Query); err == nil { c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"}) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } } //模擬請求: // 登記時(shí)間和結(jié)賬時(shí)間符合條件 //$ curl "localhost:8085/bookable?check_in=2030-04-16&check_out=2030-04-17" //{"message":"Booking dates are valid!"} // // 登記時(shí)間在結(jié)賬時(shí)間之后, 不滿足gtfield校驗(yàn)規(guī)則 //$ curl "localhost:8085/bookable?check_in=2030-03-10&check_out=2030-03-09" //{"error":"Key: 'Booking.CheckOut' Error:Field validation for 'CheckOut' failed on the 'gtfield' tag"} // // 登記時(shí)間在當(dāng)前時(shí)間之前,不滿足自定義的驗(yàn)證器 //$ curl "localhost:8085/bookable?check_in=2000-03-09&check_out=2000-03-10" //{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}%
另外結(jié)構(gòu)體級別的驗(yàn)證采用如下的方式注冊, v.RegisterStructValidation(UserStructLevelValidation, User{}), 請參考struct-lvl-validation example(https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations)
感謝各位的閱讀,以上就是“Golang GinWeb之怎么請求參數(shù)綁定和驗(yàn)證”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Golang GinWeb之怎么請求參數(shù)綁定和驗(yàn)證這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!
當(dāng)前標(biāo)題:GolangGinWeb之怎么請求參數(shù)綁定和驗(yàn)證
文章源于:http://muchs.cn/article16/piohdg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、App設(shè)計(jì)、Google、網(wǎng)站制作、做網(wǎng)站、手機(jī)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)