Go
package main
import (
"fmt"
"github.com/go-playground/validator"
)
// MyStruct .. validate:"is-awesome"是一个结构体标签,它告诉验证器使用名为is-awesome的验证规则来验证String字段。
type MyStruct struct {
String string `validate:"is-awesome"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
//注册一个自定义验证函数ValidateMyVal,它将被用来验证标签为is-awesome的字段。
validate.RegisterValidation("is-awesome", ValidateMyVal)
s := MyStruct{String: "awesome"}
err := validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):%+v\n", err)
}
s.String = "not awesome"
err = validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateMyVal implements validator.Func
func ValidateMyVal(fl validator.FieldLevel) bool {
return fl.Field().String() == "awesome"
}
Err(s):
Key: 'MyStruct.String' Error:Field validation for 'String' failed on the 'is-awesome' tag
示例代码2
custom
Go
package main
import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
"github.com/go-playground/validator/v10"
)
// DbBackedUser 用户结构体,由数据库支持
type DbBackedUser struct {
Name sql.NullString `validate:"required"` // 可以为NULL的字符串,验证规则为必填
Age sql.NullInt64 `validate:"required"` // 可以为NULL的整数,验证规则为必填
}
// 使用单一实例的验证器,它缓存结构体信息
var validate *validator.Validate
func main() {
// 创建一个新的验证器实例
validate = validator.New()
// 注册所有sql.Null*类型,使用自定义的ValidateValuer函数
validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
// 构建对象进行验证
// Name字段为空字符串但Valid为true,表示非NULL;Age字段为0且Valid为false,表示NULL
x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
// 对x进行结构体验证
err := validate.Struct(x)
// 如果验证失败,打印错误信息
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateValuer实现了validator.CustomTypeFunc接口
func ValidateValuer(field reflect.Value) interface{} {
// 如果field实现了driver.Valuer接口
if valuer, ok := field.Interface().(driver.Valuer); ok {
// 尝试获取valuer的值
val, err := valuer.Value()
if err == nil {
return val // 如果没有错误,返回值
}
// 如果有错误,可以根据需要处理
}
return nil // 如果没有实现Valuer接口或有错误,返回nil
}
Go
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) Struct(s interface{}) error {
return v.StructCtx(context.Background(), s)
}
// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
// and also allows passing of context.Context for contextual validation information.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
val := reflect.ValueOf(s)
top := val
if val.Kind() == reflect.Ptr && !val.IsNil() {
val = val.Elem()
}
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
return &InvalidValidationError{Type: reflect.TypeOf(s)}
}
// good to validate
vd := v.pool.Get().(*validate)
vd.top = top
vd.isPartial = false
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
参考validator/_examples at master · go-playground/validator · GitHub