validator自定义验证
validator是golang的一个可扩展字段验证框架
自定义标签验证
-
第三方类型,需要采取自定义类型的验证
-
有一些偏底层的内容,不方便加tag,可能各方都在调用,这时候可以采用各自的自定义验证
package validate
import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
)
type DbBackedUser struct {
// 第三方类型,需要采取自定义类型的验证
Name sql.NullString `v:"required"`
Age sql.NullInt64 `v:"required"`
Loc Location `v:"required"`
}
type Location struct {
X float64 // 也可以加校验
Y float64
}
// 有一些偏底层的内容,不方便加tag,可能各方都在调用,这时候可以采用自定义的验证
func CustomFieldTest() {
validate.RegisterCustomTypeFunc(ValidateSqlValue, sql.NullInt64{}, sql.NullString{}, sql.NullFloat64{})
validate.RegisterCustomTypeFunc(ValidateLocation)
x := DbBackedUser{
Name: sql.NullString{String: "kk", Valid: true},
Age: sql.NullInt64{Int64: 20, Valid: true}, // // Valid is true if Int64 is not NULL
Loc: Location{3.5, 1.5},
}
err := validate.Struct(x)
if err != nil {
fmt.Println(err)
}
}
func ValidateSqlValue(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(driver.Valuer); ok {
val ,err := valuer.Value()
if err == nil {
return val
} else {
return nil
}
}
return nil
}
func ValidateLocation(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(Location); ok {
if valuer.X != 0 && valuer.Y != 0 {
return fmt.Sprintf("point(%v, %v)", valuer.X, valuer.Y)
} else {
return nil
}
}
return nil
}
自定义结构体验证
- 对结构体添加额外验证,例如业务上的验证,安全性的验证
package validate
import (
"fmt"
"github.com/go-playground/validator/v10"
"reflect"
"strings"
)
// 添加一些业务验证,补充验证
type StructLevelUser struct {
FirstName string
LastName string
Age uint8 `v:"gte=0,lte=130"`
Email string `fld:"e-mail,e-mail2" v:"required,email"` // 定义别名 e-mail
}
func StructLevel() {
// 注册标签名,定义别的标签名
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
name := strings.SplitN(field.Tag.Get("fld"), ",", 2)[0]
// 返回第一个
if name != "-" {
return name
}
return ""
})
// 注册结构体校验
validate.RegisterStructValidation(func(sl validator.StructLevel) {
user := sl.Current().Interface().(StructLevelUser)
if len(user.LastName) == 0 && len(user.FirstName) == 0 {
sl.ReportError(user.FirstName, "fname", "FirstName", "fnamelname", "")
sl.ReportError(user.LastName, "lname", "LastName", "fnamelname", "")
}
}, StructLevelUser{})
user := &StructLevelUser{
FirstName: "a",
LastName: "c",
Age: 100,
Email: "ss@163.com",
}
err := validate.Struct(user)
if err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
fmt.Println(err)
return
}
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err)
}
return
}
}
自定义标签
顾名思义,自定义一些标签去验证,使用一些除了预定义标签外的标签
package validate
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type CustomValidateUser struct {
Name string `v:"required,is-zhangsan"`
Gender int `v:"gender"` // 没有gender这个预定义tag
}
func CustomValidate() {
validate.RegisterValidation("is-zhangsan", func(fl validator.FieldLevel) bool {
return fl.Field().String() == "zhangsan"
})
validate.RegisterValidation("gender", func(fl validator.FieldLevel) bool {
i := fl.Field().Int()
if i != 0 && i != 1 {
return false
}
return true
})
s := CustomValidateUser{
Name: "zhangsan2",
Gender: 1,
}
err := validate.Struct(s)
if err != nil {
fmt.Println(err)
}
}