- Updated docs ( much more to come ) - v9 is much simpler to use. v8 vs v9 improvements ``` benchmark old ns/op new ns/op delta BenchmarkFieldSuccess-8 118 147 +24.58% BenchmarkFieldFailure-8 758 417 -44.99% BenchmarkFieldDiveSuccess-8 2471 876 -64.55% BenchmarkFieldDiveFailure-8 3172 1185 -62.64% BenchmarkFieldCustomTypeSuccess-8 300 321 +7.00% BenchmarkFieldCustomTypeFailure-8 775 416 -46.32% BenchmarkFieldOrTagSuccess-8 1122 1119 -0.27% BenchmarkFieldOrTagFailure-8 1167 715 -38.73% BenchmarkStructLevelValidationSuccess-8 548 399 -27.19% BenchmarkStructLevelValidationFailure-8 558 749 +34.23% BenchmarkStructSimpleCustomTypeSuccess-8 623 673 +8.03% BenchmarkStructSimpleCustomTypeFailure-8 1381 1056 -23.53% BenchmarkStructPartialSuccess-8 1036 789 -23.84% BenchmarkStructPartialFailure-8 1734 1105 -36.27% BenchmarkStructExceptSuccess-8 888 1212 +36.49% BenchmarkStructExceptFailure-8 1036 1004 -3.09% BenchmarkStructSimpleCrossFieldSuccess-8 773 656 -15.14% BenchmarkStructSimpleCrossFieldFailure-8 1487 968 -34.90% BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 1261 1000 -20.70% BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2055 1324 -35.57% BenchmarkStructSimpleSuccess-8 519 534 +2.89% BenchmarkStructSimpleFailure-8 1429 1039 -27.29% BenchmarkStructSimpleSuccessParallel-8 146 144 -1.37% BenchmarkStructSimpleFailureParallel-8 551 419 -23.96% BenchmarkStructComplexSuccess-8 3269 2678 -18.08% BenchmarkStructComplexFailure-8 8436 6342 -24.82% BenchmarkStructComplexSuccessParallel-8 1024 874 -14.65% BenchmarkStructComplexFailureParallel-8 3536 2875 -18.69% benchmark old allocs new allocs delta BenchmarkFieldSuccess-8 0 0 +0.00% BenchmarkFieldFailure-8 4 4 +0.00% BenchmarkFieldDiveSuccess-8 28 11 -60.71% BenchmarkFieldDiveFailure-8 32 16 -50.00% BenchmarkFieldCustomTypeSuccess-8 2 2 +0.00% BenchmarkFieldCustomTypeFailure-8 4 4 +0.00% BenchmarkFieldOrTagSuccess-8 1 1 +0.00% BenchmarkFieldOrTagFailure-8 6 5 -16.67% BenchmarkStructLevelValidationSuccess-8 5 2 -60.00% BenchmarkStructLevelValidationFailure-8 5 8 +60.00% BenchmarkStructSimpleCustomTypeSuccess-8 3 2 -33.33% BenchmarkStructSimpleCustomTypeFailure-8 9 9 +0.00% BenchmarkStructPartialSuccess-8 9 6 -33.33% BenchmarkStructPartialFailure-8 14 11 -21.43% BenchmarkStructExceptSuccess-8 7 12 +71.43% BenchmarkStructExceptFailure-8 9 10 +11.11% BenchmarkStructSimpleCrossFieldSuccess-8 4 3 -25.00% BenchmarkStructSimpleCrossFieldFailure-8 9 8 -11.11% BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 7 4 -42.86% BenchmarkStructSimpleCrossStructCrossFieldFailure-8 12 9 -25.00% BenchmarkStructSimpleSuccess-8 1 0 -100.00% BenchmarkStructSimpleFailure-8 9 9 +0.00% BenchmarkStructSimpleSuccessParallel-8 1 0 -100.00% BenchmarkStructSimpleFailureParallel-8 9 9 +0.00% BenchmarkStructComplexSuccess-8 15 8 -46.67% BenchmarkStructComplexFailure-8 60 53 -11.67% BenchmarkStructComplexSuccessParallel-8 15 8 -46.67% BenchmarkStructComplexFailureParallel-8 60 53 -11.67% benchmark old bytes new bytes delta BenchmarkFieldSuccess-8 0 0 +0.00% BenchmarkFieldFailure-8 432 192 -55.56% BenchmarkFieldDiveSuccess-8 464 201 -56.68% BenchmarkFieldDiveFailure-8 896 396 -55.80% BenchmarkFieldCustomTypeSuccess-8 32 32 +0.00% BenchmarkFieldCustomTypeFailure-8 432 192 -55.56% BenchmarkFieldOrTagSuccess-8 4 16 +300.00% BenchmarkFieldOrTagFailure-8 448 208 -53.57% BenchmarkStructLevelValidationSuccess-8 160 32 -80.00% BenchmarkStructLevelValidationFailure-8 160 288 +80.00% BenchmarkStructSimpleCustomTypeSuccess-8 36 32 -11.11% BenchmarkStructSimpleCustomTypeFailure-8 640 392 -38.75% BenchmarkStructPartialSuccess-8 272 256 -5.88% BenchmarkStructPartialFailure-8 730 464 -36.44% BenchmarkStructExceptSuccess-8 250 480 +92.00% BenchmarkStructExceptFailure-8 272 448 +64.71% BenchmarkStructSimpleCrossFieldSuccess-8 80 72 -10.00% BenchmarkStructSimpleCrossFieldFailure-8 536 288 -46.27% BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 112 80 -28.57% BenchmarkStructSimpleCrossStructCrossFieldFailure-8 576 304 -47.22% BenchmarkStructSimpleSuccess-8 4 0 -100.00% BenchmarkStructSimpleFailure-8 640 392 -38.75% BenchmarkStructSimpleSuccessParallel-8 4 0 -100.00% BenchmarkStructSimpleFailureParallel-8 640 392 -38.75% BenchmarkStructComplexSuccess-8 244 128 -47.54% BenchmarkStructComplexFailure-8 3609 2833 -21.50% BenchmarkStructComplexSuccessParallel-8 244 128 -47.54% BenchmarkStructComplexFailureParallel-8 3609 2833 -21.50% ```pull/256/head
parent
852e5ff9f9
commit
b0883e6ed8
@ -0,0 +1,101 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
|
||||||
|
"gopkg.in/go-playground/validator.v9" |
||||||
|
) |
||||||
|
|
||||||
|
// User contains user information
|
||||||
|
type User struct { |
||||||
|
FirstName string `validate:"required"` |
||||||
|
LastName string `validate:"required"` |
||||||
|
Age uint8 `validate:"gte=0,lte=130"` |
||||||
|
Email string `validate:"required,email"` |
||||||
|
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
|
||||||
|
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
|
||||||
|
} |
||||||
|
|
||||||
|
// Address houses a users address information
|
||||||
|
type Address struct { |
||||||
|
Street string `validate:"required"` |
||||||
|
City string `validate:"required"` |
||||||
|
Planet string `validate:"required"` |
||||||
|
Phone string `validate:"required"` |
||||||
|
} |
||||||
|
|
||||||
|
// use a single instance of Validate, it caches struct info
|
||||||
|
var validate *validator.Validate |
||||||
|
|
||||||
|
func main() { |
||||||
|
|
||||||
|
validate = validator.New() |
||||||
|
|
||||||
|
validateStruct() |
||||||
|
validateVariable() |
||||||
|
} |
||||||
|
|
||||||
|
func validateStruct() { |
||||||
|
|
||||||
|
address := &Address{ |
||||||
|
Street: "Eavesdown Docks", |
||||||
|
Planet: "Persphone", |
||||||
|
Phone: "none", |
||||||
|
} |
||||||
|
|
||||||
|
user := &User{ |
||||||
|
FirstName: "Badger", |
||||||
|
LastName: "Smith", |
||||||
|
Age: 135, |
||||||
|
Email: "Badger.Smith@gmail.com", |
||||||
|
FavouriteColor: "#000-", |
||||||
|
Addresses: []*Address{address}, |
||||||
|
} |
||||||
|
|
||||||
|
// returns nil or ValidationErrors ( map[string]*FieldError )
|
||||||
|
err := validate.Struct(user) |
||||||
|
if err != nil { |
||||||
|
|
||||||
|
// this check is only needed when your code could produce
|
||||||
|
// an invalid value for validation such as interface with nil
|
||||||
|
// value most including myself do not usually have code like this.
|
||||||
|
if _, ok := err.(*validator.InvalidValidationError); ok { |
||||||
|
fmt.Println(err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
for _, err := range err.(validator.ValidationErrors) { |
||||||
|
|
||||||
|
fmt.Println(err.Namespace()) |
||||||
|
fmt.Println(err.Field()) |
||||||
|
fmt.Println(err.StructNamespace()) // can differ when a custom TagNameFunc is registered or
|
||||||
|
fmt.Println(err.StructField()) // by passing alt name to ReportError like below
|
||||||
|
fmt.Println(err.Tag()) |
||||||
|
fmt.Println(err.ActualTag()) |
||||||
|
fmt.Println(err.Kind()) |
||||||
|
fmt.Println(err.Type()) |
||||||
|
fmt.Println(err.Value()) |
||||||
|
fmt.Println(err.Param()) |
||||||
|
fmt.Println() |
||||||
|
} |
||||||
|
|
||||||
|
// from here you can create your own error messages in whatever language you wish
|
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// save user to database
|
||||||
|
} |
||||||
|
|
||||||
|
func validateVariable() { |
||||||
|
|
||||||
|
myEmail := "joeybloggs.gmail.com" |
||||||
|
|
||||||
|
errs := validate.Var(myEmail, "required,email") |
||||||
|
|
||||||
|
if errs != nil { |
||||||
|
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
|
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// email ok, move on
|
||||||
|
} |
@ -1,155 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"errors" |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
|
|
||||||
sql "database/sql/driver" |
|
||||||
|
|
||||||
"gopkg.in/go-playground/validator.v8" |
|
||||||
) |
|
||||||
|
|
||||||
// User contains user information
|
|
||||||
type User struct { |
|
||||||
FirstName string `validate:"required"` |
|
||||||
LastName string `validate:"required"` |
|
||||||
Age uint8 `validate:"gte=0,lte=130"` |
|
||||||
Email string `validate:"required,email"` |
|
||||||
FavouriteColor string `validate:"hexcolor|rgb|rgba"` |
|
||||||
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
|
|
||||||
} |
|
||||||
|
|
||||||
// Address houses a users address information
|
|
||||||
type Address struct { |
|
||||||
Street string `validate:"required"` |
|
||||||
City string `validate:"required"` |
|
||||||
Planet string `validate:"required"` |
|
||||||
Phone string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
config := &validator.Config{TagName: "validate"} |
|
||||||
|
|
||||||
validate = validator.New(config) |
|
||||||
|
|
||||||
validateStruct() |
|
||||||
validateField() |
|
||||||
} |
|
||||||
|
|
||||||
func validateStruct() { |
|
||||||
|
|
||||||
address := &Address{ |
|
||||||
Street: "Eavesdown Docks", |
|
||||||
Planet: "Persphone", |
|
||||||
Phone: "none", |
|
||||||
} |
|
||||||
|
|
||||||
user := &User{ |
|
||||||
FirstName: "Badger", |
|
||||||
LastName: "Smith", |
|
||||||
Age: 135, |
|
||||||
Email: "Badger.Smith@gmail.com", |
|
||||||
FavouriteColor: "#000", |
|
||||||
Addresses: []*Address{address}, |
|
||||||
} |
|
||||||
|
|
||||||
// returns nil or ValidationErrors ( map[string]*FieldError )
|
|
||||||
errs := validate.Struct(user) |
|
||||||
|
|
||||||
if errs != nil { |
|
||||||
|
|
||||||
fmt.Println(errs) // output: 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
|
|
||||||
err := errs.(validator.ValidationErrors)["User.Addresses[0].City"] |
|
||||||
fmt.Println(err.Field) // output: City
|
|
||||||
fmt.Println(err.Tag) // output: required
|
|
||||||
fmt.Println(err.Kind) // output: string
|
|
||||||
fmt.Println(err.Type) // output: string
|
|
||||||
fmt.Println(err.Param) // output:
|
|
||||||
fmt.Println(err.Value) // output:
|
|
||||||
|
|
||||||
// from here you can create your own error messages in whatever language you wish
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// save user to database
|
|
||||||
} |
|
||||||
|
|
||||||
func validateField() { |
|
||||||
myEmail := "joeybloggs.gmail.com" |
|
||||||
|
|
||||||
errs := validate.Field(myEmail, "required,email") |
|
||||||
|
|
||||||
if errs != nil { |
|
||||||
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// email ok, move on
|
|
||||||
} |
|
||||||
|
|
||||||
var validate2 *validator.Validate |
|
||||||
|
|
||||||
type valuer struct { |
|
||||||
Name string |
|
||||||
} |
|
||||||
|
|
||||||
func (v valuer) Value() (sql.Value, error) { |
|
||||||
|
|
||||||
if v.Name == "errorme" { |
|
||||||
return nil, errors.New("some kind of error") |
|
||||||
} |
|
||||||
|
|
||||||
if v.Name == "blankme" { |
|
||||||
return "", nil |
|
||||||
} |
|
||||||
|
|
||||||
if len(v.Name) == 0 { |
|
||||||
return nil, nil |
|
||||||
} |
|
||||||
|
|
||||||
return v.Name, nil |
|
||||||
} |
|
||||||
|
|
||||||
// ValidateValuerType implements validator.CustomTypeFunc
|
|
||||||
func ValidateValuerType(field reflect.Value) interface{} { |
|
||||||
if valuer, ok := field.Interface().(sql.Valuer); ok { |
|
||||||
val, err := valuer.Value() |
|
||||||
if err != nil { |
|
||||||
// handle the error how you want
|
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
return val |
|
||||||
} |
|
||||||
|
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func main2() { |
|
||||||
|
|
||||||
config := &validator.Config{TagName: "validate"} |
|
||||||
|
|
||||||
validate2 = validator.New(config) |
|
||||||
validate2.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) |
|
||||||
|
|
||||||
validateCustomFieldType() |
|
||||||
} |
|
||||||
|
|
||||||
func validateCustomFieldType() { |
|
||||||
val := valuer{ |
|
||||||
Name: "blankme", |
|
||||||
} |
|
||||||
|
|
||||||
errs := validate2.Field(val, "required") |
|
||||||
if errs != nil { |
|
||||||
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "required" tag
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// all ok
|
|
||||||
} |
|
Loading…
Reference in new issue