Gin 框架 -十一-: 驗證器 Validator 使用

1. 介紹

validator 是一個開源的驗證器包,可以快速校驗輸入信息是否符合自定規則。目前Star 7.8k, 源碼地址: https://github.com/go-playground/validator

1.1 安裝

go get github.com/go-playground/validator

1.2 引用

import "github.com/go-playground/validator"

1.3 示例

代碼:

package main
import (
 "fmt"
 "github.com/gin-gonic/gin"
 "github.com/go-playground/validator/v10"
)
// 定義一個添加用戶參數結構體
type AddUserPost struct {
 Name  string `json:"name" validate:"required"`        //必填
 Email string `json:"email" validate:"required,email"` // 必填,並且格式是email
 Age   uint8    `json:"age" validate:"gte=18,lte=30"` // 年齡範圍
}
// 簡單示例
func main() {
 engine := gin.Default()
 engine.POST("/valid", func(context *gin.Context) {
  var adduserPost  AddUserPost
  // 接收參數
  err := context.ShouldBindJSON(&adduserPost)
  if err != nil {
   context.JSON(500,gin.H{"msg":err})
   return
  }
  fmt.Printf("adduserPost: %+v\n",adduserPost)
  // 使用Validate驗證
  validate := validator.New()
  err = validate.Struct(adduserPost)
  if err != nil {
   fmt.Println(err)
   context.JSON(500,gin.H{"msg":err.Error()})
   return
  }
  context.JSON(200,gin.H{"msg":"success"})
 })
 _ = engine.Run()
}

請求:

# email不合法時
➜ curl -X POST http://127.0.0.1:8080/valid -d '{"name":"張三","email":"123","age":21}'
{"msg":"Key: 'AddUserPost.Email' Error:Field validation for 'Email' failed on the 'email' tag"}
# age 不在指定範圍時
➜ curl -X POST http://127.0.0.1:8080/valid -d '{"name":"張三","email":"123@163.com","age":17}'
{"msg":"Key: 'AddUserPost.Age' Error:Field validation for 'Age' failed on the 'gte' tag"}
# 姓名不填時
➜ curl -X POST http://127.0.0.1:8080/valid -d '{"name":"","email":"123@163.com","age":20}'
{"msg":"Key: 'AddUserPost.Name' Error:Field validation for 'Name' failed on the 'required' tag"}

2. 改成中文

2.1 代碼

package main
import (
 "github.com/gin-gonic/gin"
 "github.com/go-playground/locales/zh"
 ut "github.com/go-playground/universal-translator"
 "github.com/go-playground/validator/v10"
 zhs "github.com/go-playground/validator/v10/translations/zh"
)
var (
 validate = validator.New()          // 實例化驗證器
 chinese  = zh.New()                 // 獲取中文翻譯器
 uni      = ut.New(chinese, chinese) // 設置成中文翻譯器
 trans, _ = uni.GetTranslator("zh")  // 獲取翻譯字典
)
type User struct {
 Name  string `form:"name" validate:"required,min=3,max=5"`
 Email string `form:"email" validate:"email"`
 Age   int8   `form:"age" validate:"gte=18,lte=20"`
}

func main() {
 engine := gin.Default()
 engine.GET("/language", func(context *gin.Context) {
  var user User
  err := context.ShouldBindQuery(&user)
  if err != nil {
   context.JSON(500, gin.H{"msg": err})
   return
  }
  // 註冊翻譯器
  _ = zhs.RegisterDefaultTranslations(validate, trans)
  // 使用驗證器驗證
  err = validate.Struct(user)
  if err != nil {
   if errors, ok := err.(validator.ValidationErrors); ok {
    // 翻譯,並返回
    context.JSON(500, gin.H{
     "翻譯前": errors.Error(),
     "翻譯後": errors.Translate(trans),
    })
    return
   }
  }
  context.JSON(200,gin.H{"msg":"success"})
 })
 _ = engine.Run()
}

2.2 請求

# 不傳參數
➜ curl -X GET http://127.0.0.1:8080/language
{
    "翻譯前":"Key: 'User.Name' Error:Field validation for 'Name' failed on the 'required' tag
Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag
Key: 'User.Age' Error:Field validation for 'Age' failed on the 'gte' tag",
    "翻譯後":{
        "User.Age":"Age必須大於或等於18",
        "User.Email":"Email必須是一個有效的郵箱",
        "User.Name":"Name爲必填字段"
    }
}

3. 校驗規則

整理一些常用的規則

WKJvJa

更多規則,則可查看文檔: https://github.com/go-playground/validator

4. 自定義規則

4.1 代碼

package main
import (
 "fmt"
 "github.com/go-playground/validator/v10"
)
// 驗證pre
type CustomParam struct {
 Pre string `validate:"pre=go_"`
}
func main()  {
 // 實例化驗證器
 validate = validator.New()
 // 註冊自定義標籤
 _ = validate.RegisterValidation("pre", ValidatePre)
 cusParam := CustomParam{
  Pre: "php_",
 }
 err := validate.Struct(cusParam)
 fmt.Println(err)
}
// 自定義驗證規則
func ValidatePre(fl validator.FieldLevel) bool {
 return fl.Field().String() == "go_"
}

4.2 請求返回

Key: 'CustomParam.Pre' Error:Field validation for 'Pre' failed on the 'pre' tag

5. 在 Gin 中使用

5.1 代碼

package main
import (
 "github.com/gin-gonic/gin"
 "github.com/gin-gonic/gin/binding"
 "github.com/go-playground/validator/v10"
 "net/http"
 "time"
)
// 定義結構體
type User struct {
 Name string `form:"name" binding:"required,min=3,max=5" `
 BirthDate time.Time `form:"date" binding:"required,birth" time_format:"2006-01-02"`
}

// 運行程序
func main()  {
 engine := gin.Default()
  // 註冊自定義驗證標籤:birth
 if validate,ok  := binding.Validator.Engine().(*validator.Validate);ok {
  validate.RegisterValidation("birth",checkBirthDate)
 }
  // 接收請求
 engine.GET("/valid", func(context *gin.Context) {
  var user User
    // 集成驗證
  err := context.ShouldBindQuery(&user)
  if err != nil {
   context.JSON(http.StatusBadRequest,gin.H{"error":err.Error()})
   return
  }
  context.JSON(http.StatusOK,gin.H{"msg":"success"})
 })
 _ = engine.Run()
}
// 檢測生日
func checkBirthDate(fl validator.FieldLevel) bool {
 t,ok := fl.Field().Interface().(time.Time)
 if ok {
  // 當前時間應該大於生日時間
  if time.Now().After(t) {
   return true
  }
 }
 return false
}

5.2 請求返回

# name錯誤時
➜  curl -X GET http://127.0.0.1:8080/valid?name=張三&date=2020-01-01
{"error":"Key: 'User.Name' Error:Field validation for 'Name' failed on the 'min' tag"}
# 自定義birth格式錯誤時
➜  curl -X GET http://127.0.0.1:8080/valid?name=張是三&date=2020
{"error":"parsing time \"2020\" as \"2006-01-02\": cannot parse \"\" as \"-\""}
# 都正確
➜  curl -X GET http://127.0.0.1:8080/valid?name=張是三&date=2020-10-10
{"msg":"success"}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/qJGza5GS8bZnnArzz1h2jg