日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
GolangGinWeb框架4-請(qǐng)求參數(shù)綁定和驗(yàn)證

 簡(jiǎn)介

成都創(chuàng)新互聯(lián)公司公司2013年成立,公司自成立以來始終致力于為企業(yè)提供官網(wǎng)建設(shè)、移動(dòng)互聯(lián)網(wǎng)業(yè)務(wù)開發(fā)(成都小程序開發(fā)、手機(jī)網(wǎng)站建設(shè)、重慶App定制開發(fā)等),并且包含互聯(lián)網(wǎng)基礎(chǔ)服務(wù)(域名、主機(jī)服務(wù)、企業(yè)郵箱、網(wǎng)絡(luò)營(yíng)銷等)應(yīng)用服務(wù);以先進(jìn)完善的建站體系及不斷開拓創(chuàng)新的精神理念,幫助企業(yè)客戶實(shí)現(xiàn)互聯(lián)網(wǎng)業(yè)務(wù),嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過硬的技術(shù)實(shí)力獲得客戶的一致贊譽(yù)。

本文接著上文(Golang GinWeb框架3-自定義日志格式和輸出方式/啟禁日志顏色)繼續(xù)探索GinWeb框架

模型綁定和驗(yàn)證

使用模型綁定來綁定請(qǐng)求體到一個(gè)Go類型上. 目前支持JSON,XML,YAML以及標(biāo)準(zhǔn)表單(如foo=bar&boo=baz)的綁定.

Gin使用go-playground/validator/v10包來驗(yàn)證請(qǐng)求, 關(guān)于tags在驗(yàn)證中使用詳見(https://godoc.org/github.com/go-playground/validator#hdr-Baked_In_Validators_and_Tags)

注意:綁定前請(qǐng)確認(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ò)誤, 請(qǐng)求將以狀態(tài)碼400返回失敗信息:c.AbortWithError(400, err).SetType(ErrorTypeBind), 響應(yīng)中設(shè)置Content-Type頭為text/plain; charset=utf-8.如果手動(dòng)設(shè)置響應(yīng)碼,會(huì)警告響應(yīng)頭已經(jīng)設(shè)置,比如提示: [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422, 如果想要更好的控制這些行為,建議使用下面對(duì)應(yīng)的ShoudBind方法.

Should bind

1. 方法: ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML, ShouldBindHeader

2. 特點(diǎn): 這些方法底層使用ShouldBindWith. 如果出現(xiàn)綁定錯(cuò)誤, 會(huì)返回錯(cuò)誤, 開發(fā)者可以控制和恰當(dāng)?shù)奶幚磉@些錯(cuò)誤.

當(dāng)使用綁定方法時(shí), Gin嘗試根據(jù)類型頭Content-Type header自動(dòng)推斷要使用的綁定器. 如果你已經(jīng)確認(rèn)需要綁定的類型,可以直接使用底層的MustBindWith或ShouldBindWith方法.

你也可以針對(duì)特殊的字段指定required標(biāo)簽值, 如果某個(gè)字段指定了:binding:"required"標(biāo)簽, 但是在綁定時(shí)該字段為空會(huì)返回錯(cuò)誤.

如以下代碼綁定JSON:

 
 
 
 
  1. package main
  2. import (
  3.   "github.com/gin-gonic/gin"
  4.   "net/http"
  5. )
  6. // Binding from JSON
  7. type Login struct {
  8.   User string `form:"user" json:"user" xml:"user"  binding:"required"` //分別定義form,json,xml,binding等標(biāo)簽
  9.   //Password string `form:"password" json:"password" xml:"password" binding:"required"`
  10.   Password string `form:"password" json:"password" xml:"password" binding:"-"`
  11. }
  12. func main() {
  13.   router := gin.Default()
  14.   // Example for binding JSON ({"user": "manu", "password": "123"})
  15.   router.POST("/loginJSON", func(c *gin.Context) {
  16.     var json Login
  17.     if err := c.ShouldBindJSON(&json); err != nil {
  18.       c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  19.       return
  20.     }
  21.     if json.User != "manu" || json.Password != "123" {
  22.       c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
  23.       return
  24.     }
  25.     c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
  26.   })
  27.   // Example for binding XML (
  28.   //  
  29.   //  
  30.   //    user
  31.   //    123
  32.   //  )
  33.   router.POST("/loginXML", func(c *gin.Context) {
  34.     var xml Login
  35.     if err := c.ShouldBindXML(&xml); err != nil {
  36.       c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  37.       return
  38.     }
  39.     if xml.User != "manu" || xml.Password != "123" {
  40.       c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
  41.       return
  42.     }
  43.     c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
  44.   })
  45.   // Example for binding a HTML form (user=manu&password=123)
  46.   router.POST("/loginForm", func(c *gin.Context) {
  47.     var form Login
  48.     // This will infer what binder to use depending on the content-type header.
  49.     if err := c.ShouldBind(&form); err != nil {
  50.       c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  51.       return
  52.     }
  53.     if form.User != "manu" || form.Password != "123" {
  54.       c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
  55.       return
  56.     }
  57.     c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
  58.   })
  59.   // Listen and serve on 0.0.0.0:8080
  60.   router.Run(":8080")
  61. }
  62. //模擬請(qǐng)求: curl -v -X POST http://localhost:8080/loginJSON -H 'content-type: application/json' -d '{ "user": "manu", "password": "123" }'

跳過驗(yàn)證: 與binding:"required"標(biāo)簽對(duì)應(yīng)的是binding:"-", 表示該字段不做綁定, 所以綁定時(shí)該字段為空不會(huì)報(bào)錯(cuò).

自定義驗(yàn)證器

你也可以自己注冊(cè)一個(gè)自定義驗(yàn)證器, 示例代碼請(qǐng)參考(https://github.com/gin-gonic/examples/blob/master/custom-validation/server.go)

 
 
 
 
  1. package main
  2. import (
  3.   "net/http"
  4.   "time"
  5.   "github.com/gin-gonic/gin"
  6.   "github.com/gin-gonic/gin/binding"
  7.   "github.com/go-playground/validator/v10"
  8. )
  9. // Booking contains binded and validated data.
  10. // Booking結(jié)構(gòu)中定義了包含綁定器和日期驗(yàn)證器標(biāo)簽
  11. type Booking struct {
  12.   CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`  //登記時(shí)間
  13.   CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`  //gtfield=CheckIn表示結(jié)賬時(shí)間必須大于登記時(shí)間
  14. }
  15. // 定義日期驗(yàn)證器
  16. var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
  17.   date, ok := fl.Field().Interface().(time.Time)  //利用反射獲取到字段值 -> 轉(zhuǎn)為接口 -> 類型斷言(時(shí)間類型)
  18.   if ok {
  19.     today := time.Now()
  20.     if today.After(date) {  //如果當(dāng)前時(shí)間在checkIn字段時(shí)間之后,返回false,即登記時(shí)間不能早于當(dāng)前的時(shí)間
  21.       return false
  22.     }
  23.   }
  24.   return true
  25. }
  26. func main() {
  27.   route := gin.Default()
  28.   //對(duì)binding.Validator.Engine()接口進(jìn)行類型斷言,斷言類型為Validate結(jié)構(gòu),如果斷言成功,就將自定義的驗(yàn)證器注冊(cè)到Gin內(nèi)部
  29.   if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
  30.     // - if the key already exists, the previous validation function will be replaced. 該注冊(cè)方法會(huì)將已經(jīng)存在的驗(yàn)證器替換
  31.     // - this method is not thread-safe it is intended that these all be registered prior to any validation
  32.     // 注冊(cè)方法不是線程安全的, 在驗(yàn)證開始前,需要保證所有的驗(yàn)證器都注冊(cè)成功
  33.     v.RegisterValidation("bookabledate", bookableDate)
  34.   }
  35.   route.GET("/bookable", getBookable)
  36.   route.Run(":8085")
  37. }
  38. func getBookable(c *gin.Context) {
  39.   var b Booking
  40.   if err := c.ShouldBindWith(&b, binding.Query); err == nil {
  41.     c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
  42.   } else {
  43.     c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  44.   }
  45. }
  46. //模擬請(qǐng)求:
  47. // 登記時(shí)間和結(jié)賬時(shí)間符合條件
  48. //$ curl "localhost:8085/bookable?check_in=2030-04-16&check_out=2030-04-17"
  49. //{"message":"Booking dates are valid!"}
  50. //
  51. // 登記時(shí)間在結(jié)賬時(shí)間之后, 不滿足gtfield校驗(yàn)規(guī)則
  52. //$ curl "localhost:8085/bookable?check_in=2030-03-10&check_out=2030-03-09"
  53. //{"error":"Key: 'Booking.CheckOut' Error:Field validation for 'CheckOut' failed on the 'gtfield' tag"}
  54. //
  55. // 登記時(shí)間在當(dāng)前時(shí)間之前,不滿足自定義的驗(yàn)證器
  56. //$ curl "localhost:8085/bookable?check_in=2000-03-09&check_out=2000-03-10"
  57. //{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}%

另外結(jié)構(gòu)體級(jí)別的驗(yàn)證采用如下的方式注冊(cè), v.RegisterStructValidation(UserStructLevelValidation, User{}), 請(qǐng)參考struct-lvl-validation example(https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations)

參考文檔

Gin官方倉(cāng)庫(kù):https://github.com/gin-gonic/gin


網(wǎng)站欄目:GolangGinWeb框架4-請(qǐng)求參數(shù)綁定和驗(yàn)證
文章分享:http://m.5511xx.com/article/dppejic.html