• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    golang常用库之字段参数验证库-validator使用详解

    golang常用库:gorilla/mux-http路由库使用
    golang常用库:配置文件解析库-viper使用
    golang常用库:操作数据库的orm框架-gorm基本使用
    golang常用库:字段参数验证库-validator使用

    一、背景

    在平常开发中,特别是在web应用开发中,为了验证输入字段的合法性,都会做一些验证操作。比如对用户提交的表单字段进行验证,或者对请求的API接口字段进行验证,验证字段的合法性,保证输入字段值的安全,防止用户的恶意请求。

    一般的做法是用正则表达式,一个字段一个字段的进行验证。一个一个字段验证的话,写起来比较繁琐。那有没更好的方法,进行字段的合法性验证?有, 这就是下面要介绍的 validator 这个验证组件。

    代码地址:
    https://github.com/go-playground/validator

    文档地址:
    https://github.com/go-playground/validator/blob/master/README.md

    二、功能介绍

    这个验证包 github.com/go-playground/validator 验证功能非常多。

    标记之间特殊符号说明

    范围比较验证

    doc: https://github.com/go-playground/validator/blob/master/README.md#comparisons

    范围验证: 切片、数组和map、字符串,验证其长度;数值,验证大小范围

    例子:

    type User struct {
     Name string `json:"name" validate:"min=0,max=35"`
     Age unit8 `json:"age" validate:"lte=0,gte=90"`
    }

    更多功能请参看文档 validator comparisons doc

    字符串验证

    doc: https://github.com/go-playground/validator/blob/master/README.md#strings

    例子:

    type User struct { 
     Name string `validate:"contains=tom"` 
     Age int `validate:"min=1"`
    }

    更多功能请参看文档 validator strings doc

    字段验证

    doc: https://github.com/go-playground/validator/blob/master/README.md#fields

    eqcsfield:跨不同结构体字段验证,比如说 Struct1 Filed1,与结构体Struct2 Field2相等,

    type Struct1 struct {
     Field1 string `validate:eqcsfield=Struct2.Field2`
     Struct2 struct {
     Field2 string 
     }
    }
    type User struct { 
     Name string `validate:"lte=4"` 
     Age int `validate:"min=20"` 
     Password string `validate:"min=10"`
     Password2 string `validate:"eqfield=Password"`
    }

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

    type User struct {
     Name string `validate:"lte=4"` 
     Age int `validate:"min=20"` 
     Password string `validate:"min=10,nefield=Name"`
    }

    更多功能请参看文档:validator Fields DOC

    网络验证

    doc: https://github.com/go-playground/validator/blob/master/README.md#network

    更多功能请参看文档:validator network DOC

    Format

    doc: https://github.com/go-playground/validator/blob/master/README.md#format

    base64:字段值是否包含有效的base64值

    更多功能请参看文档 validator strings doc

    其他

    请参看文档: https://github.com/go-playground/validator/blob/master/README.md#other

    三、安装

    go get:

    go get github.com/go-playground/validator/v10

    在文件中引用validator包:

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

    四、validator使用

    文档:https://github.com/go-playground/validator/blob/master/README.md#examples

    例子1:验证单个字段变量值

    validation1.go

    package main
    
    import (
    	"fmt"
    
    	"github.com/go-playground/validator/v10"
    )
    
    func main() {
    	validate := validator.New()
    
    	var boolTest bool
    	err := validate.Var(boolTest, "required")
    	if err != nil {
    		fmt.Println(err)
    	}
    	var stringTest string = ""
    	err = validate.Var(stringTest, "required")
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	var emailTest string = "test@126.com"
    	err = validate.Var(emailTest, "email")
    	if err != nil {
    		fmt.Println(err)
    	} else {
    		fmt.Println("success") // 输出: success。 说明验证成功
    	}
    
    	emailTest2 := "test.126.com"
    	errs := validate.Var(emailTest2, "required,email")
    	if errs != nil {
    		fmt.Println(errs) // 输出: Key: "" Error:Field validation for "" failed on the "email" tag。验证失败
    	}
    
    	fmt.Println("\r\nEnd!!")
     
    }

    运行输出:

    go run simple1.go
    Key: '' Error:Field validation for '' failed on the 'required' tag
    Key: '' Error:Field validation for '' failed on the 'required' tag
    success
    Key: '' Error:Field validation for '' failed on the 'email' tag

    End!!

    例子2:验证结构体struct

    from:struct validate

    validation_struct.go,这个程序还列出了效验出错字段的一些信息,

    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"`
    	Addresses []*Address `validate:"required,dive,required"`
    }
    
    type Address struct {
    	Street string `validate:"required"`
    	City string `validate:"required"`
    	Planet string `validate:"required"`
    	Phone string `validate:"required"`
    }
    
    func main() {
    	address := Address{
    		Street: "Eavesdown Docks",
    		Planet: "Persphone",
    		Phone: "none",
    	}
    
    	user := User{
    		FirstName: "Badger",
    		LastName: "Smith",
    		Age: 135,
    		Email: "Badger.Smith@gmail.com",
    		Addresses: []*Address{address},
    	}
    
    	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("\r\n=========== 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
    	}
    }

    运行 输出:

    $ go run validation_struct.go
    === error msg ====
    Key: 'User.Age' Error:Field validation for 'Age' failed on the 'lte' tag
    Key: 'User.Addresses[0].City' Error:Field validation for 'City' failed on the 'required' tag

    =========== error field info ====================
    Namespace: User.Age
    Fild: Age
    StructNamespace: User.Age
    StructField: Age
    Tag: lte
    ActualTag: lte
    Kind: uint8
    Type: uint8
    Value: 135
    Param: 130

    Namespace: User.Addresses[0].City
    Fild: City
    StructNamespace: User.Addresses[0].City
    StructField: City
    Tag: required
    ActualTag: required
    Kind: string
    Type: string
    Value:
    Param:

    还可以给字段加一些其他tag信息,方面form,json的解析,如下:

    type User struct {
     FirstName string `form:"firstname" json:"firstname" validate:"required"`
    	LastName string `form:"lastname" json:"lastname" validate:"required"`
    	Age uint8 ` form:"age" json:"age"validate:"gte=0,lte=130"`
    	Email string ` form:"email" json:"email" validate:"required,email"`
    }

    用户自定义函数验证

    用户自定义函数验证字段是否合法,效验是否正确。

    例子3: 通过字段tag自定义函数

    validate.RegisterValidation

    customer_tag.go:

    package main
    
    import (
    	"fmt"
    
    	"github.com/go-playground/validator/v10"
    )
    
    type User struct {
    	Name string `form:"name" json:"name" validate:"required,CustomerValidation"` //注意:required和CustomerValidation之间不能有空格,否则panic。CustomerValidation:自定义tag-函数标签
    	Age uint8 ` form:"age" json:"age" validate:"gte=0,lte=80"` //注意:gte=0和lte=80之间不能有空格,否则panic
    }
    
    var validate *validator.Validate
    
    func main() {
    	validate = validator.New()
    	validate.RegisterValidation("CustomerValidation", CustomerValidationFunc) //注册自定义函数,前一个参数是struct里tag自定义,后一个参数是自定义的函数
    
    	user := User{
    		Name: "jimmy",
    		Age: 86,
    	}
    
    	fmt.Println("first value: ", user)
    	err := validate.Struct(user)
    	if err != nil {
    		fmt.Printf("Err(s):\n%+v\n", err)
    	}
    
    	user.Name = "tom"
    	user.Age = 29
    	fmt.Println("second value: ", user)
    	err = validate.Struct(user)
    	if err != nil {
    		fmt.Printf("Err(s):\n%+v\n", err)
    	}
    }
    
    // 自定义函数
    func CustomerValidationFunc(f1 validator.FieldLevel) bool {
     // f1 包含了字段相关信息
     // f1.Field() 获取当前字段信息
     // f1.Param() 获取tag对应的参数
     // f1.FieldName() 获取字段名称
     
    	return f1.Field().String() == "jimmy"
    }

    运行输出:

    $ go run customer.go
    first value: {jimmy 86}
    Err(s):
    Key: 'User.Age' Error:Field validation for 'Age' failed on the 'lte' tag
    second value: {tom 29}
    Err(s):
    Key: 'User.Name' Error:Field validation for 'Name' failed on the 'CustomerValidation' tag

    **注意

    上面代码user struct定义中 ,validate里的required和CustomerValidation之间不能有空格,否则运行时报panic错误:panic: Undefined validation function ' CustomerValidation' on field 'Name'

    例子4:自定义函数-直接注册函数1

    不通过字段tag自定义函数,直接注册函数。

    RegisterStructValidation

    https://github.com/go-playground/validator/blob/master/_examples/struct-level/main.go

    customer1.go

    package main
    
    import (
    	"fmt"
    
    	"github.com/go-playground/validator/v10"
    )
    
    type User struct {
    	FirstName string `json:firstname`
    	LastName string `json:lastname`
    	Age uint8 `validate:"gte=0,lte=130"`
    	Email string `validate:"required,email"`
    	FavouriteColor string `validate:"hexcolor|rgb|rgba"`
    }
    
    var validate *validator.Validate
    
    func main() {
    	validate = validator.New()
    
    	validate.RegisterStructValidation(UserStructLevelValidation, User{})
    
    	user := User{
    		FirstName: "",
    		LastName: "",
    		Age: 30,
    		Email: "TestFunc@126.com",
    		FavouriteColor: "#000",
    	}
    
    	err := validate.Struct(user)
    	if err != nil {
    		fmt.Println(err)
    	}
    }
    
    func UserStructLevelValidation(sl validator.StructLevel) {
    	user := sl.Current().Interface().(User)
    
    	if len(user.FirstName) == 0  len(user.LastName) == 0 {
    		sl.ReportError(user.FirstName, "FirstName", "firstname", "firstname", "")
    		sl.ReportError(user.LastName, "LastName", "lastname", "lastname", "")
    	}
    }

    运行输出:

    $ go run customer1.go
    Key: 'User.FirstName' Error:Field validation for 'FirstName' failed on the 'firstname' tag
    Key: 'User.LastName' Error:Field validation for 'LastName' failed on the 'lastname' tag

    例子5:自定义函数-直接注册函数2

    RegisterCustomTypeFunc

    https://github.com/go-playground/validator/blob/master/_examples/custom/main.go

    validate.RegisterCustomTypeFunc:验证类型的自定义函数

    customer2.go:

    package main
    
    import (
    	"database/sql"
    	"database/sql/driver"
    	"fmt"
    	"reflect"
    
    	"github.com/go-playground/validator/v10"
    )
    
    type DbBackedUser struct {
    	Name sql.NullString `validate:"required"`
    	Age sql.NullInt64 `validate:"required"`
    }
    
    var validate *validator.Validate
    
    func main() {
    	validate = validator.New()
    
    	validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
    
    	// build object for validation
    	x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
    
    	err := validate.Struct(x)
    	if err != nil {
    		fmt.Printf("Err(s):\n%+v\n", err)
    	}
    }
    
    func ValidateValuer(field reflect.Value) interface{} {
    	if valuer, ok := field.Interface().(driver.Valuer); ok {
    		val, err := valuer.Value()
    		if err == nil {
    			return val
    		}
    		// handle the error how you want
    	}
    	return nil
    }

    运行输出:

    $ go run customer.go
    Err(s):
    Key: 'DbBackedUser.Name' Error:Field validation for 'Name' failed on the 'required' tag
    Key: 'DbBackedUser.Age' Error:Field validation for 'Age' failed on the 'required' tag

    注意,这个函数
    RegisterCustomTypeFunc,它上面有2行注释:

    // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
    //
    // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation

    它是一个验证数据类型自定义函数,NOTE:这个方法不是线程安全的

    五、参考

    https://github.com/go-playground/validator/blob/master/README.mdhttps://github.com/go-playground/validator/tree/master/_examples

    总结

    到此这篇关于golang常用库:字段参数验证库-validator使用的文章就介绍到这了,更多相关golang字段参数验证库validator内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • golang之数据校验的实现代码示例
    • golang之数据验证validator的实现
    • golang validator参数校验的实现
    上一篇:Windows下Goland的环境搭建过程详解
    下一篇:golang常用库之gorilla/mux-http路由库使用详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    golang常用库之字段参数验证库-validator使用详解 golang,常用,库之,字段,参数,