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"
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM