项目地址:https://github.com/go-playground/validator
gin使用的验证器

type InvalidValidationError

无效验证错误,该错误很少去判断

  1. type InvalidValidationError struct {
  2. Type reflect.Type
  3. }

type ValidationErrors

验证错误信息数组

  1. type ValidationErrors []FieldError

type FieldError

  1. type FieldError interface {
  2. // 返回验证失败的标签
  3. // eg. alias "iscolor",will return "iscolor"
  4. Tag() string
  5. // 返回验证失败的真实标签
  6. // eg. alias "iscolor",will return "hexcolor|rgb|rgba|hsl|hsla"
  7. ActualTag() string
  8. // 返回验证失败的 结构体.字段
  9. // 当使用validate.Field(...)进行验证是,会返回空
  10. Namespace() string
  11. // 返回验证失败的 结构体.字段
  12. // 当使用validate.Field(...)进行验证是,会返回空
  13. StructNamespace() string
  14. // 返回验证失败的字段
  15. Field() string
  16. // 返回验证失败的字段
  17. StructField() string
  18. // 返回验证失败的值
  19. Value() interface{}
  20. // 给一个正确的值作为参考
  21. Param() string
  22. // Kind returns the Field's reflect Kind
  23. Kind() reflect.Kind
  24. // Type returns the Field's reflect Type
  25. Type() reflect.Type
  26. }

type FieldLevel

  1. type FieldLevel interface {
  2. // 返回第一层结构体
  3. Top() reflect.Value
  4. // 返回当前字段的父结构体
  5. Parent() reflect.Value
  6. // 返回当前字段的值
  7. Field() reflect.Value
  8. // 返回当前字段名
  9. FieldName() string
  10. // 返回当前字段名(真实)
  11. StructFieldName() string
  12. // 返回当前字段设定的值
  13. Param() string
  14. }

type StructLevel

  1. type StructLevel interface {
  2. //返回主验证对象
  3. Validator() *Validate
  4. // 返回第一层结构体
  5. Top() reflect.Value
  6. // 返回当前结字段的父结构体
  7. Parent() reflect.Value
  8. // 返回当前结构体
  9. Current() reflect.Value
  10. // 通过传递字段和标记信息来报告错误
  11. ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
  12. }

type Func

Func接受所有验证需求的现场级接口。验证成功时,返回值应该为true。

  1. type Func func(fl FieldLevel) bool

type FuncCtx

  1. type FuncCtx func(ctx context.Context, fl FieldLevel) bool

type StructLevelFunc

  1. type StructLevelFunc func(sl StructLevel)

type StructLevelFuncCtx

  1. type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)

type Validate

func New() Validate 返回一个“validate”的新实例
func (v
Validate) SetTagName(name string) 更改“validate”的默认标记名
func (v Validate) Struct(s interface{}) error 结构体验证,并验证被嵌套的结构体
func (v
Validate) StructCtx(ctx context.Context, s interface{}) (err error)
func (v Validate) Var(field interface{}, tag string) error 验证单个变量
func (v
Validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull …bool) error

  • 使用给定的标签添加验证

func (v Validate) RegisterValidationCtx(tag string, fn FuncCtx, callValidationEvenIfNull …bool) error
func (v
Validate) RegisterStructValidation(fn StructLevelFunc, types …interface{})

  • 为结构体添加验证

func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types …interface{})

用法

  1. - :跳过验证,例 `validate:"-"`,常出现在嵌套验证中
  2. | :或操作,例 `validate:"rbg|rgba"`,接受rbgrgba类型的值
  3. dive :潜入切片,数组或映射,如果是多维嵌套,那么可以用多个dive,dive...
  4. structonly:不对嵌套结构体中的任何字段进行验证
  5. omitempty :如果是空值,忽略其他的验证,注意放的位置,放在最前面,表示对后面的所有要求生效
  6. required :必须字段
  7. oneof :枚举,`validate:"oneof=1 2"`
  8. required_with_all :当默些字段存在时才验证该字段 required_with_all = f1 f2
  9. required_without : 当默些字段不存在时才验证该字段 required_without = f1 f2
  10. len 对于数字型是==判断,对于其他是length判断 len = 5
  11. max 数字验证最大,其他验证length max = 5
  12. min 数字验证最小,其他验证length min = 5
  13. eq 数字与字符串验证==,其他验证length eq = 5
  14. ne eq相反,!=
  15. gt 大于
  16. gte 大于等于
  17. lt 小于
  18. lte 小于等于
  19. eqfield 判断该字段是否等于另外一个字段 eqfield=ConfirmPassword
  20. validate.VarWithValue(password, confirmpassword, "eqfield")
  21. nefield eqfield相反
  22. unique 对于数组和片,unique将确保没有重复。对于映射,unique将确保没有重复的值
  23. numeric 判断字符类型是否只包含整数或浮点数
  24. hexadecimal :验证字符串值是否包含有效的十六进制
  25. hexcolor 将验证字符串值是否包含有效的十六进制颜色,包括hashtag (#)
  26. rgb 验证字符串值是否包含有效的rgb颜色
  27. email 验证字符串值是否包含有效的电子邮件
  28. json 验证字符串值是否为json格式
  29. file 验证字符串值是否包含有效的文件路径
  30. url 将验证字符串值是否包含有效的url,必须包含一个模式,例如http://或rtmp://
  31. uri 验证字符串值是否包含有效的uri
  32. base64 验证字符串值是否包含有效的base64
  33. contains 验证字符串是否包含莫子串 contains = a
  34. containsany 验证字符串是否包含莫子串的任意一个 containsany = abc
  35. excludes contains相反,是不包含
  36. excludesall containsany相反,是不包含任意一个
  37. startswith 验证字符串是否已某个字符串开头
  38. endswith 结尾
  39. uuid 判断字符串是否是uuid类型
  40. uuid3
  41. uuid4
  42. uuid5
  43. latitude 是否包含有效的纬度
  44. longitude 是否包含有效的经度
  45. ip
  46. ipv4
  47. ipv6
  48. datetime 字符串值是否包含有效的日期
  49. tcp_addr
  50. tcp4_addr
  51. tcp6_addr
  52. ......

例一:基本使用

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. )
  6. // User contains user information
  7. type User struct {
  8. FirstName string `validate:"required"`
  9. LastName string `validate:"required"`
  10. Age uint8 `validate:"gte=0,lte=130"`
  11. Email string `validate:"required,email"`
  12. FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
  13. Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
  14. }
  15. // Address houses a users address information
  16. type Address struct {
  17. Street string `validate:"required"`
  18. City string `validate:"required"`
  19. Planet string `validate:"required"`
  20. Phone string `validate:"required"`
  21. }
  22. // use a single instance of Validate, it caches struct info
  23. var validate *validator.Validate
  24. func main() {
  25. validate = validator.New()
  26. validateStruct()
  27. validateVariable()
  28. }
  29. func validateStruct() {
  30. address := &Address{
  31. Street: "Eavesdown Docks",
  32. City : "Beijing",
  33. Planet: "Persphone",
  34. Phone: "none",
  35. }
  36. user := &User{
  37. FirstName: "Badger",
  38. LastName: "Smith",
  39. Age: 135,
  40. Email: "Badger.Smith@gmail.com",
  41. FavouriteColor: "#000",
  42. Addresses: []*Address{address},
  43. }
  44. // returns nil or ValidationErrors ( []FieldError )
  45. err := validate.Struct(user)
  46. if err != nil {
  47. for _, err := range err.(validator.ValidationErrors) {
  48. fmt.Println(err.Namespace()) //User.Age
  49. fmt.Println(err.Field()) //Age
  50. fmt.Println(err.StructNamespace()) //User.Age
  51. fmt.Println(err.StructField()) //Age
  52. fmt.Println(err.Tag()) //lte
  53. fmt.Println(err.ActualTag()) //lte
  54. fmt.Println(err.Kind()) //uint8
  55. fmt.Println(err.Type()) //uint8
  56. fmt.Println(err.Value()) //135
  57. fmt.Println(err.Param()) //130
  58. }
  59. }
  60. }
  61. func validateVariable() {
  62. myEmail := "joeybloggs.gmail.com"
  63. errs := validate.Var(myEmail, "required,email")
  64. if errs != nil {
  65. fmt.Println(errs) // Key: "" Error:Field validation for "" failed on the "email" tag
  66. return
  67. }
  68. }

例二:自定义字段(验证字段)

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. "time"
  6. )
  7. type Address struct {
  8. Street string `validate:"required"`
  9. City string `validate:"required"`
  10. Planet string `validate:"required"`
  11. Phone string `validate:"required"`
  12. Age int `validate:"min=12,max=15"`
  13. CreateAt time.Time `validate:"required,myParam"` // 日期必须大于2000-01-01
  14. }
  15. func main() {
  16. address := &Address{
  17. Street: "Eavesdown Docks",
  18. City: "beijing",
  19. Planet: "Persphone",
  20. Phone: "none",
  21. Age: 12,
  22. CreateAt : time.Now(),
  23. }
  24. validate := validator.New()
  25. //自己定义tag标签以及与之对应的处理逻辑
  26. validate.RegisterValidation("myParam", mytimeFunc)
  27. //查看是否符合验证
  28. err := validate.Struct(address)
  29. fmt.Println(err)
  30. }
  31. func mytimeFunc(fl validator.FieldLevel) bool {
  32. format:= "2006-01-02"
  33. param,_ :=time.ParseInLocation(format,"2000-01-01",time.Local)
  34. param1,ok:=fl.Field().Interface().(time.Time)
  35. if !ok || param1.Before(param){
  36. return false
  37. }
  38. return true
  39. }

例三:自定义字段(验证结构体一)

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. "time"
  6. )
  7. type Time struct {
  8. CreateTime time.Time `validate:"required,myParam"`
  9. T int
  10. }
  11. type Address struct {
  12. Street string `validate:"required"`
  13. City string `validate:"required"`
  14. Planet string `validate:"required"`
  15. Phone string `validate:"required"`
  16. Age int `validate:"min=12,max=15"`
  17. CreateAt *Time `validate:"required"` // 日期必须大于2000-01-01
  18. }
  19. func main() {
  20. CreateAt := &Time{
  21. CreateTime:time.Now(),
  22. }
  23. address := &Address{
  24. Street: "Eavesdown Docks",
  25. City: "beijing",
  26. Planet: "Persphone",
  27. Phone: "none",
  28. Age: 12,
  29. CreateAt : CreateAt,
  30. }
  31. validate := validator.New()
  32. //自己定义tag标签以及与之对应的处理逻辑
  33. validate.RegisterValidation("myParam", mytimeFunc)
  34. //查看是否符合验证
  35. err := validate.Struct(address)
  36. fmt.Println(err)
  37. }
  38. func mytimeFunc(fl validator.FieldLevel) bool {
  39. format:= "2006-01-02"
  40. param,_ :=time.ParseInLocation(format,"2000-01-01",time.Local)
  41. param1,ok:=fl.Field().Interface().(time.Time)
  42. fmt.Println(fl.FieldName())
  43. if !ok || param1.Before(param){
  44. return false
  45. }
  46. return true
  47. }

例四:自定义字段(验证结构体二)

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. "time"
  6. )
  7. type Time struct {
  8. CreateTime time.Time `validate:"required"`
  9. T int `validate:"required"`
  10. }
  11. type Address struct {
  12. Street string `validate:"required"`
  13. City string `validate:"required"`
  14. Planet string `validate:"required"`
  15. Phone string `validate:"required"`
  16. Age int `validate:"min=12,max=15"`
  17. CreateAt *Time `validate:"required"` // 日期必须大于2000-01-01,T必须<=10
  18. }
  19. func main() {
  20. CreateAt := &Time{
  21. CreateTime:time.Now(),
  22. T:11,
  23. }
  24. address := &Address{
  25. Street: "Eavesdown Docks",
  26. City: "beijing",
  27. Planet: "Persphone",
  28. Phone: "none",
  29. Age: 12,
  30. CreateAt : CreateAt,
  31. }
  32. validate := validator.New()
  33. //自己定义tag标签以及与之对应的处理逻辑
  34. validate.RegisterStructValidation(mytimeFunc, &Time{})
  35. //查看是否符合验证
  36. err := validate.Struct(address)
  37. fmt.Println(err)
  38. }
  39. func mytimeFunc(sl validator.StructLevel){
  40. format:= "2006-01-02"
  41. param,_ :=time.ParseInLocation(format,"2000-01-01",time.Local)
  42. t := sl.Current().Interface().(Time)
  43. if t.T > 10{
  44. sl.ReportError(t.T,"T","T","max","10")
  45. }
  46. if t.CreateTime.Before(param){
  47. sl.ReportError(t.T,"CreateTime","CreateTime","after","2000-01-01")
  48. }
  49. }

例五:输出中文错误提示

import “github.com/go-playground/validator/translations/zh”
该包只有一个对外函数
func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error)
ps:在与v10结合时出了问题,拉不下来

  1. .\demo2.go:28:43: cannot use validate (type *"github.com/go-playground/validator/v10".Validate)
  2. as type *"gopkg.in/go-playground/validator.v9".Validate in argument to
  3. "github.com/go-playground/validator/translations/zh".RegisterDefaultTranslations

拉下来后需要改一下源码import的内容,按下面源码改即可
或:因为只有一个文件,把代码copy下来作为一个包(推荐)
https://github.com/go-playground/validator/blob/master/translations/zh/zh.go

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/locales/zh"
  5. "github.com/go-playground/universal-translator"
  6. "github.com/go-playground/validator/v10"
  7. zh_translater "study/validate/zh"
  8. )
  9. type UserInfo struct {
  10. FirstName string `validate:"required"`
  11. LastName string `validate:"required"`
  12. Age uint8 `validate:"gte=0,lte=100"`
  13. Email string `validate:"required,email"`
  14. }
  15. func main() {
  16. //中文翻译器
  17. zh_ch := zh.New()
  18. uni := ut.New(zh_ch)
  19. trans, _ := uni.GetTranslator("zh")
  20. //验证器
  21. validate := validator.New()
  22. //验证器注册翻译器
  23. zh_translater.RegisterDefaultTranslations(validate, trans)
  24. user := &UserInfo{
  25. FirstName: "Badger",
  26. LastName: "Smith",
  27. Age: 105,
  28. Email: "",
  29. }
  30. err := validate.Struct(user)
  31. if err != nil {
  32. for _, err := range err.(validator.ValidationErrors) {
  33. //翻译错误信息
  34. fmt.Println(err.Translate(trans))
  35. }
  36. return
  37. }
  38. fmt.Println("success")
  39. }
  40. //输出:
  41. Age必须小于或等于100
  42. Email为必填字段

例六:自定义错误

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. )
  6. type UserInfo struct {
  7. Age uint8 `validate:"required,gte=0,lte=100"`
  8. Email string `validate:"required,email"`
  9. }
  10. func (self *UserInfo) GetErrors(errs validator.ValidationErrors) string{
  11. errstr := ""
  12. for _,err :=range errs{
  13. if err.Field() == "Age"{
  14. if err.Tag() == "required"{
  15. errstr += "年龄必填,"
  16. }else if err.Tag() == "gte" || err.Tag() == "lte"{
  17. errstr += "年龄需在0-100之间,"
  18. }
  19. }
  20. if err.Field() == "Email"{
  21. if err.Tag() == "required"{
  22. errstr += "邮箱必填,"
  23. }else if err.Tag() == "email"{
  24. errstr += "邮箱格式错误,"
  25. }
  26. }
  27. }
  28. return errstr
  29. }
  30. func main() {
  31. validate := validator.New()
  32. user := &UserInfo{
  33. Age: 105,
  34. Email: "",
  35. }
  36. err := validate.Struct(user)
  37. if err != nil {
  38. errstr := user.GetErrors(err.(validator.ValidationErrors))//断言
  39. fmt.Println(errstr) //年龄需在0-100之间,邮箱必填,
  40. return
  41. }
  42. fmt.Println("success")
  43. }

例七:利用反射自定义错误信息

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-playground/validator/v10"
  5. "reflect"
  6. )
  7. var validate *validator.Validate
  8. type UserInfo struct {
  9. Age uint8 `validate:"required,gte=0,lte=100" message:"年龄需在0-100之间"`
  10. Email string `validate:"required,email" message:"email字段必须为结构体"`
  11. }
  12. func StructToValidate(structInter interface{}) (map[string]string, bool) {
  13. structType := reflect.TypeOf(structInter)
  14. var resultMap map[string]string = map[string]string{}
  15. validErr := validate.Struct(structInter)
  16. if validErr != nil {
  17. for _, err := range validErr.(validator.ValidationErrors) {
  18. field, isOK := structType.FieldByName(err.Field())
  19. if isOK {
  20. // fmt.Println("validmsg------------------------>",field.Tag.Get("validmsg"))
  21. resultMap[err.Field()] = field.Tag.Get("message")
  22. }
  23. }
  24. return resultMap, false
  25. } else {
  26. return nil, true
  27. }
  28. }
  29. func main() {
  30. validate = validator.New()
  31. user := UserInfo{
  32. Age: 105,
  33. Email: "",
  34. }
  35. results, isOK :=StructToValidate(user)
  36. if !isOK{
  37. fmt.Println(results) //map[Age:年龄需在0-100之间 Email:email 字段必须为结构体]
  38. }
  39. }

例八:嵌套验证错误自定义

基于例子七:对结构体嵌结构体有用,对结构体嵌数组等暂时不行

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. type AAAA struct {
  7. Name string `name22:"bbb"`
  8. Age string `name22:"ccc"`
  9. }
  10. type AAA struct {
  11. Aaaa []AAAA `name11:"aaa"`
  12. }
  13. func main() {
  14. var a AAA
  15. at := reflect.TypeOf(a)
  16. field,ok := at.FieldByName("Aaaa")
  17. if ok {
  18. if field.Type.Kind() == reflect.Slice{
  19. tag := field.Type.Elem().Field(0).Tag.Get("name22")
  20. fmt.Println(tag) // bbb
  21. fmt.Println("------------------------")
  22. field = field.Type.Elem().Field(0)
  23. fmt.Println(field) // {Name string name22:"bbb" 0 [0] false}
  24. }
  25. }
  26. }
  1. func StructToValidate(structInter interface{}) (map[string]string, bool) {
  2. structType := reflect.TypeOf(structInter)
  3. var resultMap map[string]string = map[string]string{}
  4. validErr := validate.Struct(structInter)
  5. if validErr != nil {
  6. for _, err := range validErr.(validator.ValidationErrors) {
  7. var field reflect.StructField
  8. var isOK bool
  9. if strings.Count(err.StructNamespace(),".") == 1{
  10. field, isOK = structType.FieldByName(err.Field())
  11. }else {
  12. // 命名空间包含的.大于1,说明是嵌套验证
  13. structT := structType
  14. for i:=1;i<strings.Count(err.StructNamespace(),".");i++{
  15. fieldName := strings.Split(err.StructNamespace(),".")[i]
  16. field,isOK = structT.FieldByName(fieldName)
  17. if isOK{
  18. structT = field.Type
  19. }
  20. }
  21. field, isOK = structT.FieldByName(err.Field())
  22. }
  23. if isOK {
  24. resultMap[err.Field()] = field.Tag.Get("validmsg")
  25. }else {
  26. resultMap[err.Field()] = err.Field()+"不能为空"
  27. }
  28. }
  29. return resultMap, false
  30. }
  31. return nil, true
  32. }