What it is
go-playground/validator performs struct validation from field tags, covering required fields, ranges, formats, cross-field rules and custom validators.
Annotate struct fields with validate tags and call Struct(). Failures come back as a slice of FieldError describing which rule failed on which field.
Installation
go get github.com/go-playground/validator/v10Getting started
The smallest useful thing you can do with it, and what each part means.
go
type CreateUser struct {
Email string `validate:"required,email"`
Age int `validate:"gte=13,lte=130"`
Password string `validate:"required,min=12"`
Confirm string `validate:"eqfield=Password"`
Website string `validate:"omitempty,url"`
}
validate := validator.New(validator.WithRequiredStructEnabled())
if err := validate.Struct(input); err != nil {
var invalid validator.ValidationErrors
if errors.As(err, &invalid) {
for _, fe := range invalid {
fmt.Printf("%s failed %s\n", fe.Field(), fe.Tag())
}
}
}Advanced usage
Where the library earns its place over a simpler alternative.
go
validate.RegisterValidation("notreserved", func(fl validator.FieldLevel) bool {
return !reservedNames[strings.ToLower(fl.Field().String())]
})
// Report the JSON name, not the Go field name, so clients recognise it.
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" { return "" }
return name
})
type Signup struct {
Username string `json:"username" validate:"required,notreserved"`
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- validator: (nil)
- Struct() was passed a nil pointer or a non-struct. Check the value before validating.
- Rules on nested structs are skipped
- Add validate:"required" or validate:"dive" on the parent field; nested structs and slice elements are not descended into automatically.
Best practices
- Create one Validator and reuse it — it caches struct reflection and is safe for concurrent use.
- Register a tag-name function so errors reference the JSON field names.
- Use omitempty for optional fields, otherwise the rule fires on empty values.
- Validate at the boundary only; internal code should be able to trust its inputs.
Background
Why it exists, and what it was reacting to.
This is the validation engine behind Gin, Echo and most Go web frameworks' binding features, which is why its tag syntax is effectively a Go-wide convention.
