Skip to content

validator

Developer UtilitiesUtilitiesGo

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/v10

Getting started

The smallest useful thing you can do with it, and what each part means.

Tags and readable errors
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())
        }
    }
}
omitempty means the rule only applies when the field is non-empty, and eqfield expresses cross-field rules such as password confirmation without custom code.

Advanced usage

Where the library earns its place over a simpler alternative.

Custom rules and friendly messages
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"`
}
RegisterTagNameFunc is the detail that makes API error messages usable: without it, errors name the Go field (Username) rather than the JSON key the client actually sent.

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.