golang之数据验证validator

golang之数据验证validator

前言

普通验证对struct的数据方法比较繁琐,这里介绍一个使用比较多的包:validator

原理

将验证规则写在struct对字段tag里,在通过反射获取struct的tag,实现数据验证

安装

go get github.com/go-playground/validator

标记之间特殊符号说明

  • 逗号(,):把多个验证标记隔开。注意:逗号前面和后面都不能有空格,否则panic
  • 横线(-):跳过该字段不验证
  • 竖线(|):使用多个验证标记,但是只需要满足其中一个即可
  • required:必填
  • omitempty:如果字段未设置,则忽略它

特殊字符串验证

  • email:验证字符串是email格式。默认为必填
  • url:验证字符串是URL格式。默认为必填
  • uri:字段值是否包含有效的uri,validate:"uri"
  • ip:字段值是否包含有效的IP地址,validate:"ip"
  • ipv4:字段值是否包含有效的ipv4地址,validate:"ipv4"
  • ipv6:字段值是否包含有效的ipv6地址,validate:"ipv6"

不跨字段范围验证规则

  • max&min:max字符串最大长度,min字符串最小长度
  • len:len字符串长度必须为n,或者是数组、切片、map的len的值
  • eq:数字等于n
  • ne:数字不等n
  • gt:数字大于n
  • gte:数字大于等于n
  • lt:小于n
  • lte:小于等于n

示例(特殊字符串和不跨字段范围验证规则)

package main

import (
	"log"

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

type Users struct {
	Phone  string `validate:"required"`              // 必填
	Email  string `validate:"email"`                 // 验证字符串是email格式。默认为必填
	Url    string `validate:"url"`                   // 验证字符串是URL格式。默认为必填
	Passwd string `validate:"required,max=20,min=6"` // max字符串最大长度,min字符串最小长度
	Code   string `validate:"required,len=6"`        // len字符串长度必须为n,或者是数组、切片、map的len的值
	Eq     int    `validate:"eq=4"`                  // eq数字等于n
	Ne     int    `validate:"ne=4"`                  // ne数字不等n
	Gt     int    `validate:"gt=4"`                  // gt数字大于n
	Gte    int    `validate:"gte=4"`                 // gte数字大于等于n
	Lt     int    `validate:"lt=4"`                  // lt小于n
	Lte    int    `validate:"lte=4"`                 // lte小于等于
}

func init() {
	log.SetFlags(log.Ldate | log.Lshortfile | log.Ltime)
}

func main() {
	users := Users{
		Phone:  "1326654487",
		Email:  "1843121593@qq.com",
		Url:    "https://blog.csdn.net/guyan0319/article/details/105918559",
		Passwd: "123456",
		Code:   "123456",
		Eq:     4,
		Ne:     3,
		Gt:     5,
		Gte:    4,
		Lt:     3,
		Lte:    4,
	}
	log.Printf("users:%+v\n", users)
	validate := validator.New()
	validatErr := validate.Struct(&users)
	errs := make([]validator.FieldError, 0)
	if validatErr != nil {
		for _, err := range validatErr.(validator.ValidationErrors) {
			errs = append(errs, err)
		}
	}
	if len(errs) != 0 {
		for i := 0; i < len(errs); i++ {
			log.Println(errs[i])
		}
	}
}

字符串验证

  • contains:包含参数子串。validate:"contains=ysm" (字段的字符串值包含ysm)
  • excludes:不包含参数子串,validate:"excludes=tom" (字段的字符串值不包含tom)
  • startswith:以参数子串为前缀,validate:"startswith=golang"
  • endswith:以参数子串为后缀,validate:"startswith=world"

示例

package main

import (
	"log"

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

type Teacher struct {
	Contains   string `validate:"contains=ysm"`     // 包含参数子串。validate:"contains=ysm" (字段的字符串值包含ysm)
	Excludes   string `validate:"excludes=tom"`     // excludes:不包含参数子串,validate:"excludes=tom" (字段的字符串值不包含tom)
	Startswith string `validate:"startswith=start"` // startswith:以参数子串为前缀,validate:"startswith=golang"
	Endswith   string `validate:"endswith=end"`     // endswith:以参数子串为后缀,validate:"startswith=world"
}

func teacher() {
	teacher := Teacher{
		Contains:   "ysmisgood",
		Excludes:   "isgood",
		Startswith: "startgogo",
		Endswith:   "gogoend",
	}
	log.Printf("teacher:%+v\n", teacher)
	validate := validator.New()
	validatErr := validate.Struct(&teacher)
	errs := make([]validator.FieldError, 0)
	if validatErr != nil {
		for _, err := range validatErr.(validator.ValidationErrors) {
			errs = append(errs, err)
		}
	}
	if len(errs) != 0 {
		for i := 0; i < len(errs); i++ {
			log.Println(errs[i])
		}
	}
}

func main(){
	teacher()
}

跨字段验证

  • eqfield=Field: 必须等于 Field 的值
  • nefield=Field: 必须不等于 Field 的值
  • gtfield=Field: 必须大于 Field 的值
  • gtefield=Field: 必须大于等于 Field 的值
  • ltfield=Field: 必须小于 Field 的值
  • ltefield=Field: 必须小于等于 Field 的值
  • eqcsfield:跨不同结构体字段验证,比如说 Struct1 Filed1,与结构体Struct2 Field2相等 (字段之间为包含关系,并且只能是在Struct1 Filed1 = Struct2 Field2,但是不能Struct2 Field2 = Struct1 Filed1)
  • 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 的值;

示例

package main

import (
	"log"

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

type Student struct {
	Name     string `validate:"required,eqcsfield=Pen.StudentName"`  // eqcsfield:Name的值必须等于Pen.StudentName的值
	Passwd   string `validate:"required,max=20,min=6"`
	Repasswd string `validate:"required,max=20,min=6,eqfield=Passwd"` // eqfield必须等于passwd的值
	Pen      struct {
		StudentName string `validate:"required"`
	}
}

func student() {
	student := Student{
		Name:     "ysm",
		Passwd:   "123456",
		Repasswd: "123456",
		Pen: struct {
			StudentName string `validate:"required"`
		}{StudentName: "ysm"},
	}
	log.Printf("student:%+v\n", student)
	validate := validator.New()
	validatErr := validate.Struct(&student)
	errs := make([]validator.FieldError, 0)
	if validatErr != nil {
		for _, err := range validatErr.(validator.ValidationErrors) {
			errs = append(errs, err)
		}
	}
	if len(errs) != 0 {
		for i := 0; i < len(errs); i++ {
			log.Println(errs[i])
		}
	}
}

func main(){
	student()
}

自定义类型

  • 主要使用validator.New().RegisterValidation("tagName",tagFunc)

示例

package main

import (
	"log"

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

type Users struct {
	Phone  string `validate:"required,PhoneValidationErrors"` // 必填
	Email  string `validate:"email"`                          // 验证字符串是email格式。默认为必填
	Url    string `validate:"url"`                            // 验证字符串是URL格式。默认为必填
	Passwd string `validate:"required,max=20,min=6"`          // max字符串最大长度,min字符串最小长度
	Code   string `validate:"required,len=6"`                 // len字符串长度必须为n,或者是数组、切片、map的len的值
	Eq     int    `validate:"eq=4"`                           // eq数字等于n
	Ne     int    `validate:"ne=4"`                           // ne数字不等n
	Gt     int    `validate:"gt=4"`                           // gt数字大于n
	Gte    int    `validate:"gte=4"`                          // gte数字大于等于n
	Lt     int    `validate:"lt=4"`                           // lt小于n
	Lte    int    `validate:"lte=4"`                          // lte小于等于
}
func main() {
	users := Users{
		Phone:  "13345679878",
		Email:  "1843121593@qq.com",
		Url:    "https://blog.csdn.net/guyan0319/article/details/105918559",
		Passwd: "123456",
		Code:   "123456",
		Eq:     4,
		Ne:     3,
		Gt:     5,
		Gte:    4,
		Lt:     3,
		Lte:    4,
	}
	log.Printf("users:%+v\n", users)
	validate := validator.New()
	// 注册自定义函数
	_ = validate.RegisterValidation("PhoneValidationErrors", PhoneValidationErrors)
	validatErr := validate.Struct(&users)
	errs := make([]validator.FieldError, 0)
	if validatErr != nil {
		for _, err := range validatErr.(validator.ValidationErrors) {
			errs = append(errs, err)
		}
	}
	if len(errs) != 0 {
		for i := 0; i < len(errs); i++ {
			log.Println(errs[i])
		}
	}
}

// 返回TRUE则不会报错,返回FALSE则会报错
func PhoneValidationErrors(fl validator.FieldLevel) bool {
	return fl.Field().String() == "13345679878"
}
posted @ 2021-09-04 16:33  Myuniverse  阅读(1402)  评论(0编辑  收藏  举报