1. 程式人生 > >基於gin的golang web開發:模型驗證

基於gin的golang web開發:模型驗證

Gin除了模型繫結還提供了模型驗證功能。你可以給欄位指定特定的規則標籤,如果一個欄位用binding:"required"標籤修飾,在繫結時該欄位的值為空,那麼將返回一個錯誤。開發web api的時候大部分引數都是需要驗證的,比如email引數要驗證是否是郵箱格式、phone引數要驗證是否是手機號格式等等,使用模型驗證方法可以將驗證過程隔離在業務之外。 ### 內建的驗證標籤 Gin通過整合go-playground/validator提供模型驗證功能,並提供了很多常用驗證規則可以滿足我們大部分的開發需求。我們通過一個例子看一下怎麼使用這些驗證標籤。 ```golang type AddUserRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` // 登入密碼 Nickname string `json:"nickname" binding:"required"` // 暱稱 Mobile string `json:"mobile"` // 手機號 Email string `json:"email" binding:"required,email"` // 郵箱地址 } func AddUser(c *gin.Context) { req := sysUser.AddUserRequest{} if err := c.ShouldBind(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } ... c.String(http.StatusOK, "") } ``` 在Username欄位上增加了binding:"required"標籤,代表gin會驗證引數為必填項,如果沒有為Username欄位提供值ShouldBind返回的err中會包含相應的錯誤內容。Email欄位增加了binding:"required,email"標籤,這是一個組合驗證,代表Email是必填項的同時還要是一個正確的郵箱格式的字串。 下面例子可以看到在未通過模型驗證時,介面返回的錯誤資訊。 請求: ```json { "username":"", "password":"123qwe", "nickname": "暱稱", "mobile": "13322323232", "email": "", "qq": "234123412312" } ``` 響應: ```json { "error": "Key: 'AddUserRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag\nKey: 'AddUserRequest.Email' Error:Field validation for 'Email' failed on the 'required' tag" } ``` ### 自定義驗證 有時候內建的驗證規則可能不能滿足業務需求,這樣就需要自定義驗證規則。大致兩個步驟,1.定義一個驗證方法。2.把這個方法註冊為驗證規則。 ```golang type Booking struct { CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"` CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"` } var bookableDate validator.Func = func(fl validator.FieldLevel) bool { date, ok := fl.Field().Interface().(time.Time) if ok { today := time.Now() if today.After(date) { return false } } return true } func main() { route := gin.Default() if v, ok := binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation("bookabledate", bookableDate) } ... } ``` 這裡添加了一個叫做bookabledate的驗證規則,驗證一下引數是否大於今天。使用RegisterValidation("bookabledate", bookableDate)方法註冊為驗證規則,並且在CheckIn欄位上增加了binding:"required,bookabledate"標籤。如果驗證失敗會返回錯誤資訊: ``` Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag" ``` ### 自定義錯誤訊息 目前錯誤訊息還是英文的,對於國內使用者很不友好,介面報錯的時候基本不可能把這種錯誤訊息返回給使用者看。go-playground/validator提供了錯誤資訊的翻譯,至少先解決英文錯誤的問題。在專案下新增validator/init.go檔案。 ```golang package validator import ( "github.com/gin-gonic/gin/binding" "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" zh_translations "github.com/go-playground/validator/v10/translations/zh" ) var ( uni *ut.UniversalTranslator validate *validator.Validate trans ut.Translator ) func init() { translator := zh.New() uni = ut.New(translator, translator) trans, _ = uni.GetTranslator("zh") validate := binding.Validator.Engine().(*validator.Validate) _ = zh_translations.RegisterDefaultTranslations(validate, trans) } func Translate(err error) string { var result string errors := err.(validator.ValidationErrors) for _, err := range errors { result += err.Translate(trans) + ";" } return result } ``` 在handler中呼叫validator.Translate方法獲取錯誤訊息的中文翻譯。 ``` func AddUser(c *gin.Context) { req := sysUser.AddUserRequest{} if err := c.ShouldBind(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": validator.Translate(err)}) return } ... c.String(http.StatusOK, "") } ``` 這樣訪問介面時會看到中文的錯誤資訊: ```golang { "error": "Username為必填欄位;" } ``` 文章出處:[基於gin的golang web開發:模型驗證][source] [source]: https://www.huaface.com/arti