Go中最常用的数据校验库

2024-02-26 15:51:36 浏览数 (1)

项目地址: github.com/go-playground/validator/v10

标记

标记说明

required

必填

Field或Struct validate:"required"

omitempty

空时忽略

Field或Struct validate:"omitempty"

len

长度

Field validate:"len=0"

eq

等于

Field validate:"eq=0"

gt

大于

Field validate:"gt=0"

gte

大于等于

Field validate:"gte=0"

lt

小于

Field validate:"lt=0"

lte

小于等于

Field validate:"lte=0"

eqfield

同一结构体字段相等

Field validate:"eqfield=Field2"

nefield

同一结构体字段不相等

Field validate:"nefield=Field2"

gtfield

大于同一结构体字段

Field validate:"gtfield=Field2"

gtefield

大于等于同一结构体字段

Field validate:"gtefield=Field2"

ltfield

小于同一结构体字段

Field validate:"ltfield=Field2"

ltefield

小于等于同一结构体字段

Field validate:"ltefield=Field2"

eqcsfield

跨不同结构体字段相等

Struct1.Field validate:"eqcsfield=Struct2.Field2"

necsfield

跨不同结构体字段不相等

Struct1.Field validate:"necsfield=Struct2.Field2"

gtcsfield

大于跨不同结构体字段

Struct1.Field validate:"gtcsfield=Struct2.Field2"

gtecsfield

大于等于跨不同结构体字段

Struct1.Field validate:"gtecsfield=Struct2.Field2"

ltcsfield

小于跨不同结构体字段

Struct1.Field validate:"ltcsfield=Struct2.Field2"

ltecsfield

小于等于跨不同结构体字段

Struct1.Field validate:"ltecsfield=Struct2.Field2"

min

最大值

Field validate:"min=1"

max

最小值

Field validate:"max=2"

structonly

仅验证结构体,不验证任何结构体字段

Struct validate:"structonly"

nostructlevel

不运行任何结构级别的验证

Struct validate:"nostructlevel"

dive

向下延伸验证,多层向下需要多个dive标记

[][]string validate:"gt=0,dive,len=1,dive,required"

dive Keys & EndKeys

与dive同时使用,用于对map对象的键的和值的验证,keys为键,endkeys为值

map[string]string validate:"gt=0,dive,keys,eq=1|eq=2,endkeys,required"

required_with

其他字段其中一个不为空且当前字段不为空

Field validate:"required_with=Field1 Field2"

required_with_all

其他所有字段不为空且当前字段不为空

Field validate:"required_with_all=Field1 Field2"

required_without

其他字段其中一个为空且当前字段不为空

Field `validate:"required_without=Field1 Field2"

required_without_all

其他所有字段为空且当前字段不为空

Field validate:"required_without_all=Field1 Field2"

isdefault

是默认值

Field validate:"isdefault=0"

oneof

其中之一

Field validate:"oneof=5 7 9"

containsfield

字段包含另一个字段

Field validate:"containsfield=Field2"

excludesfield

字段不包含另一个字段

Field validate:"excludesfield=Field2"

unique

是否唯一,通常用于切片或结构体

Field validate:"unique"

alphanum

字符串值是否只包含 ASCII 字母数字字符

Field validate:"alphanum"

alphaunicode

字符串值是否只包含 unicode 字符

Field validate:"alphaunicode"

alphanumunicode

字符串值是否只包含 unicode 字母数字字符

Field validate:"alphanumunicode"

numeric

字符串值是否包含基本的数值

Field validate:"numeric"

hexadecimal

字符串值是否包含有效的十六进制

Field validate:"hexadecimal"

hexcolor

字符串值是否包含有效的十六进制颜色

Field validate:"hexcolor"

lowercase

符串值是否只包含小写字符

Field validate:"lowercase"

uppercase

符串值是否只包含大写字符

Field validate:"uppercase"

email

字符串值包含一个有效的电子邮件

Field validate:"email"

json

字符串值是否为有效的 JSON

Field validate:"json"

file

符串值是否包含有效的文件路径,以及该文件是否存在于计算机上

Field validate:"file"

url

符串值是否包含有效的 url

Field validate:"url"

uri

符串值是否包含有效的 uri

Field validate:"uri"

base64

字符串值是否包含有效的 base64值

Field validate:"base64"

contains

字符串值包含子字符串值

Field validate:"contains=@"

containsany

字符串值包含子字符串值中的任何字符

Field validate:"containsany=abc"

containsrune

字符串值包含提供的特殊符号值

Field validate:"containsrune=☢"

excludes

字符串值不包含子字符串值

Field validate:"excludes=@"

excludesall

字符串值不包含任何子字符串值

Field validate:"excludesall=abc"

excludesrune

字符串值不包含提供的特殊符号值

Field validate:"containsrune=☢"

startswith

字符串以提供的字符串值开始

Field validate:"startswith=abc"

endswith

字符串以提供的字符串值结束

Field validate:"endswith=abc"

ip

字符串值是否包含有效的 IP 地址

Field validate:"ip"

ipv4

字符串值是否包含有效的 ipv4地址

Field validate:"ipv4"

datetime

字符串值是否包含有效的 日期

Field validate:"datetime"

单字段校验

模拟对前端传参进行校验

单字段多个条件 校验

代码语言:javascript复制
package main

import (
 "fmt"
 "strings"

 "github.com/go-playground/locales/en"
 "github.com/go-playground/locales/zh"
 ut "github.com/go-playground/universal-translator"
 "github.com/go-playground/validator/v10"

 zhtrans "github.com/go-playground/validator/v10/translations/zh"
 // entrans "github.com/go-playground/validator/v10/translations/en"
)

/*
https://www.cnblogs.com/jiujuan/p/13823864.html

https://www.liwenzhou.com/posts/Go/validator-usages/

https://juejin.cn/post/7056823502640250893

https://juejin.cn/post/6847902214279659533
*/
type Student struct {
 Name  string `validate:required`
 Email string `validate:"email"`
 Age   int    `validate:"max=30,min=12"`
}

func main() {
 en := en.New() //英文翻译器
 zh := zh.New() //中文翻译器

 // 第一个参数是必填,如果没有其他的语言设置,就用这第一个
 // 后面的参数是支持多语言环境(
 // uni := ut.New(en, en) 也是可以的
 // uni := ut.New(en, zh, tw)
 uni := ut.New(en, zh)
 trans, _ := uni.GetTranslator("zh") //获取需要的语言

 student := Student{
  Name:  "tom",
  Email: "testemal",
  Age:   40,
 }
 validate := validator.New()

 zhtrans.RegisterDefaultTranslations(validate, trans)

 err := validate.Struct(student)
 if err != nil {
  // fmt.Println(err)

  errs := err.(validator.ValidationErrors)
  fmt.Println(removeStructName(errs.Translate(trans)))
 }
}

func removeStructName(fields map[string]string) map[string]string {
 result := map[string]string{}

 for field, err := range fields {
  result[field[strings.Index(field, ".") 1:]] = err
 }
 return result
}

在线代码[1]

输出:

map[Age:Age必须小于或等于30 Email:Email必须是一个有效的邮箱]

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type User struct {
 FirstName string               `validate:"required"`
 LastName  string               `validate:"required"`
 Age       uint8                `validate:"gte=0,lte=130"`
 Email     string               `validate:"required,email"`
 Test      string               `validate:"len=0|min=6,max=24,len=0|alphanum"` // 或者 条件之一, 使用|。 但每个,都是独立的一个逻辑,之间是&的关系(有一个不满足就报错"Error:Field validation"),且条件没有传递,所以要在alphanum前面也加一个len=0|。 而max=24和长度为0不冲突,所以不需要加
 Products  []CreateOrderProduct `validate:"min=1"`                             // 产品列表
}

type CreateOrderProduct struct {
 SkuCode  string `json:"skuCode"`  // sku编码
 Quantity int64  `json:"quantity"` // 商品数量
}

//  oneof:只能是列举出的值其中一个,这些值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围,validate:"oneof=red green"
// https://www.cnblogs.com/jiujuan/p/13823864.html

func main() {

 user := &User{
  FirstName: "Badger",
  LastName:  "Smith",
  Age:       115,
  Email:     "Badger.Smith@gmail.com",
  Test:      "",
  Products:  []CreateOrderProduct{},
 }

 validate := validator.New()
 err := validate.Struct(user)
 if err != nil {
  fmt.Println("=== error msg ====")
  fmt.Println(err)

  //if _, ok := err.(*validator.InvalidValidationError); ok {
  // fmt.Println(err)
  // return
  //}
  //
  //fmt.Println("rn=========== error field info ====================")
  //for _, err := range err.(validator.ValidationErrors) {
  // // 列出效验出错字段的信息
  // fmt.Println("Namespace: ", err.Namespace())
  // fmt.Println("Fild: ", err.Field())
  // fmt.Println("StructNamespace: ", err.StructNamespace())
  // fmt.Println("StructField: ", err.StructField())
  // fmt.Println("Tag: ", err.Tag())
  // fmt.Println("ActualTag: ", err.ActualTag())
  // fmt.Println("Kind: ", err.Kind())
  // fmt.Println("Type: ", err.Type())
  // fmt.Println("Value: ", err.Value())
  // fmt.Println("Param: ", err.Param())
  // fmt.Println()
  //}

  // from here you can create your own error messages in whatever language you wish
  return
 }
}

在线代码[2]

输出:

代码语言:javascript复制
=== error msg ====
Key: 'User.Products' Error:Field validation for 'Products' failed on the 'min' tag

跨字段验证

eqfield 同一结构体字段验证相等

eqfield=Field:必须等于 Field 的值

最常见的就是输入2次密码验证

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

// 多字段联合校验

// eqfield:同一结构体字段验证相等,最常见的就是输入2次密码验证

type Account struct {
 Name      string `validate:"lte=16"`
 Age       int    `validate:"min=20"`
 Password  string `validate:"min=8"`
 Password2 string `validate:"eqfield=Password"`
}

func main() {
 account := &Account{
  Name:      "Badger",
  Age:       115,
  Password:  "qwert12345",
  Password2: "111111",
 }

 validate := validator.New()
 err := validate.Struct(account)
 if err != nil {
  fmt.Println("=== error msg ====")
  fmt.Println(err)

  if _, ok := err.(*validator.InvalidValidationError); ok {
   fmt.Println(err)
   return
  }

  fmt.Println("rn=========== error field info ====================")
  for _, err := range err.(validator.ValidationErrors) {
   // 列出效验出错字段的信息
   fmt.Println("Namespace: ", err.Namespace())
   fmt.Println("Fild: ", err.Field())
   fmt.Println("StructNamespace: ", err.StructNamespace())
   fmt.Println("StructField: ", err.StructField())
   fmt.Println("Tag: ", err.Tag())
   fmt.Println("ActualTag: ", err.ActualTag())
   fmt.Println("Kind: ", err.Kind())
   fmt.Println("Type: ", err.Type())
   fmt.Println("Value: ", err.Value())
   fmt.Println("Param: ", err.Param())
   fmt.Println()
  }

  // from here you can create your own error messages in whatever language you wish
  return
 }
}

在线运行[3]

输出:

代码语言:javascript复制
=== error msg ====
Key: 'Account.Password2' Error:Field validation for 'Password2' failed on the 'eqfield' tag

=========== error field info ====================
Namespace:  Account.Password2
Fild:  Password2
StructNamespace:  Account.Password2
StructField:  Password2
Tag:  eqfield
ActualTag:  eqfield
Kind:  string
Type:  string
Value:  111111
Param:  Password

nefield:同一结构体字段验证不相等

nefield=Field:必须不等于 Field 的值

例如,验证密码不能和用户名相同

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

// 多字段联合校验

// eqfield:同一结构体字段验证相等,最常见的就是输入2次密码验证

type Account struct {
 Name     string `validate:"lte=16"`
 Age      int    `validate:"min=20"`
 Password string `validate:"min=1,nefield=Name"`
}

func main() {
 account := &Account{
  Name:     "Badger",
  Age:      115,
  Password: "Badger",
 }

 validate := validator.New()
 err := validate.Struct(account)
 if err != nil {
  fmt.Println("=== error msg ====")
  fmt.Println(err)

  if _, ok := err.(*validator.InvalidValidationError); ok {
   fmt.Println(err)
   return
  }

  fmt.Println("rn=========== error field info ====================")
  for _, err := range err.(validator.ValidationErrors) {
   // 列出效验出错字段的信息
   fmt.Println("Namespace: ", err.Namespace())
   fmt.Println("Fild: ", err.Field())
   fmt.Println("StructNamespace: ", err.StructNamespace())
   fmt.Println("StructField: ", err.StructField())
   fmt.Println("Tag: ", err.Tag())
   fmt.Println("ActualTag: ", err.ActualTag())
   fmt.Println("Kind: ", err.Kind())
   fmt.Println("Type: ", err.Type())
   fmt.Println("Value: ", err.Value())
   fmt.Println("Param: ", err.Param())
   fmt.Println()
  }

  // from here you can create your own error messages in whatever language you wish
  return
 }
}

输出:

代码语言:javascript复制
=== error msg ====
Key: 'Account.Password' Error:Field validation for 'Password' failed on the 'nefield' tag

=========== error field info ====================
Namespace:  Account.Password
Fild:  Password
StructNamespace:  Account.Password
StructField:  Password
Tag:  nefield
ActualTag:  nefield
Kind:  string
Type:  string
Value:  Badger
Param:  Name

类似的还有

  • gtfield=Field:必须大于 Field 的值。
  • gtefield=Field: 必须大于等于 Field 的值。
  • ltfield=Field:必须小于 Field 的值。
  • ltefield=Field:必须小于等于 Field 的值。

eqcsfield=Other.Field:必须等于 struct Other 中 Field 的值。

用于验证跨结构体的两个字段是否相等,需要指定另一个字段的名称或路径作为参数,比如 eqcsfield=Other.Field 中的 Other.Field 就是指定的另一个字段。

在使用该选项时,会比较当前字段和指定的另一个字段的值是否相等,如果相等则验证通过,否则验证失败。这个选项通常用于验证密码和确认密码等类似的场景。

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type Struct1 struct {
 Field1  string `validate:"eqcsfield=Struct2.Field2""`
 Struct2 struct {
  Field2 string
 }
}

func main() {

 s := &Struct1{
  Field1:  "必须一致",
  Struct2: struct{ Field2 string }{Field2: "没有一致"},
 }

 validate := validator.New()
 err := validate.Struct(s)
 if err != nil {
  fmt.Println("=== error msg ====")
  fmt.Println(err)

  if _, ok := err.(*validator.InvalidValidationError); ok {
   fmt.Println(err)
   return
  }

  fmt.Println("rn=========== error field info ====================")
  for _, err := range err.(validator.ValidationErrors) {
   // 列出效验出错字段的信息
   fmt.Println("Namespace: ", err.Namespace())
   fmt.Println("Fild: ", err.Field())
   fmt.Println("StructNamespace: ", err.StructNamespace())
   fmt.Println("StructField: ", err.StructField())
   fmt.Println("Tag: ", err.Tag())
   fmt.Println("ActualTag: ", err.ActualTag())
   fmt.Println("Kind: ", err.Kind())
   fmt.Println("Type: ", err.Type())
   fmt.Println("Value: ", err.Value())
   fmt.Println("Param: ", err.Param())
   fmt.Println()
  }

  // from here you can create your own error messages in whatever language you wish
  return
 }
}

输出:

代码语言:javascript复制
=== error msg ====
Key: 'Struct1.Field1' Error:Field validation for 'Field1' failed on the 'eqcsfield' tag

=========== error field info ====================
Namespace:  Struct1.Field1
Fild:  Field1
StructNamespace:  Struct1.Field1
StructField:  Field1
Tag:  eqcsfield
ActualTag:  eqcsfield
Kind:  string
Type:  string
Value:  必须一致
Param:  Struct2.Field2

看起来只支持嵌套结构体,不支持两个独立的结构体之间某个字段的比较

eqfieldeqcsfield 的区别在于它们用于比较的字段的位置不同:eqfield 比较的是同一个结构体中的两个字段的值,而 eqcsfield 比较的是当前结构体中的某个字段和另一个(子?)结构体中的字段的值

类似的还有

  • necsfield=Other.Field:必须不等于 struct Other 中 Field 的值。
  • gtcsfield=Other.Field:必须大于 struct Other 中 Field 的值;
  • gtecsfield=Other.Field:必须大于等于 struct Other 中 Field 的值。
  • ltcsfield=Other.Field:必须小于 struct Other 中 Field 的值。
  • ltecsfield=Other.Field:必须小于等于 struct Other 中 Field 的值。

如何比较两个独立结构体中某两个字段的值?


required_with=Field1 Field2:在 Field1 或者 Field2 存在时,必须;

required_with=Field2:在 Field2被填写(即不为空)时,Field1也必须不能为空

代码语言:javascript复制
package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

type User struct {
    Name     string `validate:"required"`
    Email    string `validate:"required_with=Phone"`
    Phone    string
}

func main() {
    user1 := User{
        Name:     "John",
        Email:    "",
        Phone:    "",
    }

    user2 := User{
        Name:     "Mary",
        Email:    "mary@example.com",
        Phone:    "",
    }

    validate := validator.New()

    err1 := validate.Struct(user1)
    if err1 != nil {
        fmt.Println(err1)
    }

    err2 := validate.Struct(user2)
    if err2 != nil {
        fmt.Println(err2)
    }
}

验证通过~

在这个例子中,User 结构体包含 Name、Email 和 Phone 字段。Email 字段被标记为 required_with=Phone,这意味着当 Phone 字段被填写时,Email 字段也必须被填写。

而如果把user1改为:

代码语言:javascript复制
user1 := User{
  Name:  "John",
  Email: "",
  Phone: "123",
 }

则会报错:

代码语言:javascript复制
Key: 'User.Email' Error:Field validation for 'Email' failed on the 'required_with' tag

验证不通过


required_with_all=Field1 Field2:在 Field1 与 Field2 都存在时,必须;(仅当所有其他指定的字段都存在时,验证字段才必须存在)

要么有这个tag的全部为空,如果有一个不为空,那所有其他的也都不能为空~

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type User6 struct {
 Name  string `validate:"required"`
 Email string `validate:"required_with_all=Phone"`
 Phone string `validate:"required_with_all=Email"`
}

func main() {
 user := User6{
  Name:  "John",
  Email: "",
  Phone: "",
 }

 validate := validator.New()

 err := validate.Struct(user)
 if err != nil {
  fmt.Println(err)
 }
}

Email 和 Phone 字段都被标记为 required_with_all,

这意味着当 Email 和 Phone

  • 要么全都为空
  • 如果其中的任何一个被填写时,另一个也必须被填写(不为空即可,可以不一样)

所以上面代码可以验证通过

如下也是合法的:

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type User6 struct {
 Name  string `validate:"required"`
 Email string `validate:"required_with_all=Phone"`
 Phone string `validate:"required_with_all=Email"`
}

func main() {
 user := User6{
  Name:  "John",
  Email: "1",
  Phone: "2",
 }

 validate := validator.New()

 err := validate.Struct(user)
 if err != nil {
  fmt.Println(err)
 }
}

类似的还有:

required_without=Field1 Field2:在 Field1 或者 Field2 不存在时,必须;

Field1 Field2字段其中(至少)一个为空,则当前字段不能为空

代码语言:javascript复制
package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

type User struct {
    Name     string `validate:"required"`
    Email    string
    Phone    string
    Address  string `validate:"required_without=Email Phone"`// Email Phone 中间不能加逗号
}

func main() {
    user1 := User{
        Name:     "John",
        Email:    "",
        Phone:    "",
        Address:  "123 Main St.",
    }

    user2 := User{
        Name:     "Mary",
        Email:    "mary@example.com",
        Phone:    "",
        Address:  "",
    }

    validate := validator.New()

    err1 := validate.Struct(user1)
    if err1 != nil {
        fmt.Println("err1:", err1)
    }

    err2 := validate.Struct(user2)
    if err2 != nil {
       fmt.Println("err2:", err2)
    }
}

输出:

代码语言:javascript复制
err2: Key: 'User7.Address' Error:Field validation for 'Address' failed on the 'required_without' tag

User 结构体包含 Name、Email、Phone 和 Address 字段。Address 字段被标记为 required_without=Email Phone,这意味着当 Email 和 Phone 字段至少一个为空时,Address 字段必须被填写。

required_without_all=Field1 Field2:在 Field1 与 Field2 都存在时,必须; (仅当所有其他指定字段都不存在时,验证字段才必须...)

Field1 Field2字段都为空时,则当前字段不能为空

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type User7 struct {
 Name    string `validate:"required"`
 Email   string
 Phone   string
 Address string `validate:"required_without_all=Email Phone"`
}

func main() {
 user1 := User7{
  Name:    "John",
  Email:   "",
  Phone:   "111",
  Address: "123 Main St.",
 }

 user2 := User7{
  Name:    "Mary",
  Email:   "",
  Phone:   "",
  Address: "",
 }

 validate := validator.New()

 err1 := validate.Struct(user1)
 if err1 != nil {
  fmt.Println("err1:", err1)
 }

 err2 := validate.Struct(user2)
 if err2 != nil {
  fmt.Println("err2:", err2)
 }
}

输出:

代码语言:javascript复制
err2: Key: 'User7.Address' Error:Field validation for 'Address' failed on the 'required_without_all' tag

验证proto

可参考 Go gRPC进阶-proto数据验证(九) [4]


更复杂的判断

代码语言:javascript复制
type User struct {
Age uint8 validate:"gte=0,lte=130"
Email string validate:"required,email"
Score int validate:"min=1" // 分数
Gender string validate:"required,oneof=男 女"
}

如果满足以下任意一项则认为通过:

  • Gender=男,Age小于35,Score大于60
  • Gender=女,Age小于40,Score大于50

这种用validator/v10能判断吗?..

这种复杂的验证规则超出了validator/v10的基本功能,需要进行自定义验证函数。可以使用validator/v10的Func函数,通过编写自定义的验证函数来实现这种验证规则。

如下是一个示例代码:

代码语言:javascript复制
package main

import (
 "fmt"

 "github.com/go-playground/validator/v10"
)

type User struct {
 Age    uint8  `validate:"gte=0,lte=130,customValidation"`
 Email  string `validate:"required,email"`
 Score  int    `validate:"required,gte=0,customValidation"`
 Gender string `validate:"required,oneof=男 女,customValidation"`
}

func validateUser(fl validator.FieldLevel) bool {

 user, ok := fl.Top().Interface().(*User)

 fmt.Println("user is:", user)

 if !ok {
  return false
 }

 if user.Gender == "男" && user.Age < 35 && user.Score > 60 {
  return true
 }
 if user.Gender == "女" && user.Age < 40 && user.Score > 50 {
  return true
 }
 return false
}

// - Gender=男,Age小于35,Score大于60
// - Gender=女,Age小于40,Score大于50

func main() {
 user := &User{
  Age:    36,
  Email:  "example@gmail.com",
  Score:  1711,
  Gender: "男",
 }

 validate := validator.New()
 err := validate.RegisterValidation("customValidation", validateUser)
 if err != nil {
  fmt.Println(err)
  return
 }

 err = validate.Struct(user)

 fmt.Println("err is:", err)
 if err != nil {
  fmt.Println(err)
  return
 }

 fmt.Println("validation succeeded")
}

输出:

代码语言:javascript复制
user is: &{36 example@gmail.com 1711 男}
user is: &{36 example@gmail.com 1711 男}
user is: &{36 example@gmail.com 1711 男}
err is: Key: 'User.Age' Error:Field validation for 'Age' failed on the 'customValidation' tag
Key: 'User.Score' Error:Field validation for 'Score' failed on the 'customValidation' tag
Key: 'User.Gender' Error:Field validation for 'Gender' failed on the 'customValidation' tag
Key: 'User.Age' Error:Field validation for 'Age' failed on the 'customValidation' tag
Key: 'User.Score' Error:Field validation for 'Score' failed on the 'customValidation' tag
Key: 'User.Gender' Error:Field validation for 'Gender' failed on the 'customValidation' tag

参考资料:

golang之验证器validator[5]

【Go】数据验证-validator[6]

Go 使用validator进行后端数据校验[7]

gopkg.in/go-playground/validator.v10[8]

结构字段验证--validator.v9[9]

Golang验证器之validator使用详解[10]

Go 每日一库之 validator[11]

golang常用库:字段参数验证库-validator使用[12]

参考资料

[1]

在线代码: https://go.dev/play/p/p0r79v_RuSO

[2]

在线代码: https://go.dev/play/p/tjZ6PurLe-p

[3]

在线运行: https://go.dev/play/p/UNj1WhSY1fM

[4]

Go gRPC进阶-proto数据验证(九) : https://www.cnblogs.com/FireworksEasyCool/p/12761033.html

[5]

golang之验证器validator: https://www.cnblogs.com/xingxia/p/golang_validator.html

[6]

【Go】数据验证-validator: https://blog.csdn.net/qq_42887507/article/details/120934568

[7]

Go 使用validator进行后端数据校验: https://www.admpub.com/blog/post/admin/Go-使用validator进行后端数据校验

[8]

gopkg.in/go-playground/validator.v10: https://pkg.go.dev/gopkg.in/go-playground/validator.v10

[9]

结构字段验证--validator.v9: https://www.cnblogs.com/zhzhlong/p/10033234.html

[10]

Golang验证器之validator使用详解: https://www.jb51.net/article/260639.htm

[11]

Go 每日一库之 validator: https://darjun.github.io/2020/04/04/godailylib/validator/

[12]

golang常用库:字段参数验证库-validator使用: https://www.cnblogs.com/jiujuan/p/13823864.html

0 人点赞