Help us shape the future of Go! Take the 2026 Go Developer Survey

valigo

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

README

codecov build Goreport GoDoc

valigo

valigo validates Go structs by rules written in Go, next to the struct, by pointers to its fields. The compiler checks every rule, a valid object is validated without allocations about 4 times faster than by go-playground/validator, and the errors come translated to the language of the user, with stable codes for the clients that translate themselves.

b.Field(&u.Email).As(str.Of).Required().Email()
b.Field(&u.Age).As(num.Of).AnyOfInterval(18, 120) // the arguments are int: Max("120") doesn't compile
b.Field(&u.Name).As(num.Of)                       // doesn't compile: string does not satisfy num.Number

Documentation: insei.github.io/valigo — get started, why valigo, the rules of every type, performance.

For AI agents: the skill with the current API, and the documentation as one file, llms-full.txt.

Installation

Go 1.27 or newer is required, the configurator uses generic methods.

go get github.com/insei/valigo@latest

Upgrading from v0.0.x: see Upgrading.

Example

type User struct {
	Name     string
	Email    string
	Age      int
	Phone    *string
	Tags     []string
	StartsAt time.Time
	EndsAt   *time.Time
}

v := valigo.New()
valigo.Configure[User](v, func(b valigo.Configurator[User], u *User) {
	b.Field(&u.Name).As(str.Of).Trim().Required().MaxRunes(64)
	b.Field(&u.Email).As(str.Of).Required().Email()
	b.Field(&u.Age).As(num.Of).AnyOfInterval(18, 120)
	b.Field(&u.Phone).As(str.Of).E164() // a nil phone is skipped
	b.Slice(&u.Tags).As(str.Slice).MaxLen(5).Each(func(tag *str.BaseConfigurator) {
		tag.Trim().Required().MaxLen(16)
	})
	b.Field(&u.EndsAt).As(timex.Of).AfterField(&u.StartsAt) // a rule on another field
})

errs := v.ValidateTyped(ctx, &User{Name: "  Ann  ", Email: "ann.example.com", Age: 16, Tags: []string{"go", " "}})
// Should be email address (Email: ann.example.com)   code string.email
// Only interval[18 - 120] is allowed (Age: 16)       code number.interval, params {"min": 18, "max": 120}
// Should be fulfilled (Tags[1]: )                    code string.required

Rules

The configurator has Field, Slice and Map for the fields, As converts them to the configurators of their types, and a conversion that doesn't fit the field doesn't compile:

Conversion Fields Rules
str.Of string, *string, named strings Required, lengths in bytes and runes, AnyOf, Prefix, Suffix, Contains, Excludes, Alpha, Digits, Numeric, Hexadecimal, Regexp, Email, URL, IP, CIDR, MAC, Hostname, UUID, E164, Base64, JSON, Semver, HexColor, Datetime, CountryCode, CurrencyCode, CreditCard, Trim...
num.Of, num.Ptr integers, floats, named numbers, pointers to them Required, Min, Max, GreaterThan, LessThan, AnyOf, AnyOfInterval, Latitude, Longitude
timex.Of time.Time, *time.Time Required, Before, After, Between, InPast, InFuture
eq.Of, eq.Ptr any comparable: enums, bools Required, OneOf, NotOneOf, Equal, NotEqual
vuuid.Of uuid.UUID, *uuid.UUID, the separate module github.com/insei/valigo/rules/uuid Required, AnyOf
str.Slice, num.Slice, timex.Slice, eq.Slice, vuuid.Slice slices, also of pointers Required, MinLen, MaxLen, Each for the elements, Unique
b.Map(&m.X) maps Required, MinLen, MaxLen, EachKey, EachValue
  • Rules on other fields by their pointers: AfterField, MinField, MaxField, EqualField.
  • Conditions and custom rules: When and Custom on fields and on the struct, closures with the context of the request — the limits can come from a database or the settings of a tenant.
  • Absent values: nil pointers and the fields of nil nested structs are skipped by every rule except Required.
  • Your types: a conversion function of a few lines, the core has no dependencies on uuid or other packages of types.
  • Tags of go-playground/validator: b.Tags("validate") configures the rules of validate:"required,max=64" with the messages and the speed of valigo, a migration moves them to code one by one.

Errors and translations

  • Every error has the translated message, the location (Tags[1], address.city with JSON paths), the value, a stable Code and named Params
  • Messages in English, German, Spanish, French and Russian with plural forms, the language of every request from the context, an Accept-Language middleware
  • problem: the errors as application/problem+json of RFC 9457 with JSON pointers
  • The rules as the keywords of JSON Schema, vhuma.OpenAPI puts them into the OpenAPI document of huma: the clients see maxLength, format, enum of the rules
  • github.com/insei/valigo/integrations/huma, github.com/insei/valigo/integrations/gin, github.com/insei/valigo/integrations/echo: the rules of valigo in huma, gin and echo

Performance

The same struct and rules, Intel Core i9-14900HX, Go 1.27.0, see Performance:

valid object invalid object, 6 errors
hand-written code 286 ns, 0 allocs 590 ns, without messages
valigo 407 ns, 0 allocs 2 205 ns, 14 allocs, translated messages
go-playground/validator 1 785 ns, 16 allocs 4 150 ns, 69 allocs, with Error()
ozzo-validation 2 950 ns, 38 allocs 12 665 ns, 140 allocs, with Error()

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Configure

func Configure[T any](v *Validator, fn func(builder Configurator[T], m *T))

Configure configures validation rules for the struct type T, replacing the rules of previous Configure calls for T. fn receives a model with all nested pointer structs allocated, rules are configured by pointers to the model fields. Configure panics on invalid configuration, call it on application start and not concurrently with Validate.

Types

type Configurator

type Configurator[T any] struct {
	// contains filtered or unexported fields
}

Configurator configures validation rules for the struct type T. Field pointers passed to its methods must point to the fields of the model passed to the Configure function.

func (Configurator[T]) Custom

func (c Configurator[T]) Custom(fn func(ctx context.Context, h shared.StructCustomHelper, obj *T) []shared.Error)

Custom adds a custom validation function on the whole struct. The helper passed to fn is valid only during the fn call.

func (Configurator[T]) Field added in v0.1.0

func (c Configurator[T]) Field[F any](fieldPtr *F) *shared.Field[F]

Field returns the base configurator of the field, convert it to a typed one with As: b.Field(&m.Name).As(str.Of), b.Field(&m.Discount).As(num.Ptr).

func (Configurator[T]) Map added in v0.1.0

func (c Configurator[T]) Map[K comparable, V any](mapFieldPtr *map[K]V) *shared.MapFieldConfigurator[K, V]

Map returns the configurator of the map field with the rules of the map itself, EachKey and EachValue: b.Map(&m.Labels).MaxLen(10).EachKey(func(k *shared.Field[string]) { k.As(str.Of).Hostname() }).

func (Configurator[T]) Slice

func (c Configurator[T]) Slice[E any](sliceFieldPtr *[]E) *shared.SliceFieldConfigurator[E]

Slice returns the configurator of the slice field with the rules of the slice itself, convert it to a typed one with As for the rules of elements: b.Slice(&m.Tags).As(str.Slice). A pointer to a slice field is converted from its field: b.Field(&m.Tags).As(shared.SlicePtr).

func (Configurator[T]) Tags added in v0.1.0

func (c Configurator[T]) Tags(name string)

Tags configures the rules of the tag name of the fields of T and of its nested structs in the syntax of go-playground/validator, validate:"required,max=64", for a migration from it: the tags and the rules in code can be mixed in one Configure. The rules are the rules of valigo with their messages, codes and constraints: required is Required, min and max are the lengths in characters of strings, the values of numbers and the lengths of slices and maps, dive applies the next rules to the elements of a slice or the values of a map[string]V. The rules of the fields of a nil nested struct are skipped, like by go-playground/validator, unlike the rules in code. See the documentation for the list of the rules. Tags panics on an unknown rule, like Configure on invalid rules.

func (Configurator[T]) When

func (c Configurator[T]) When(fn func(ctx context.Context, obj *T) bool) Configurator[T]

When returns a Configurator whose rules are applied only if fn returns true. Conditions of chained When calls are combined with AND.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option is an interface that defines a single method, apply, which is used to apply an option to a Validator.

func WithErrorsTransformer added in v0.0.2

func WithErrorsTransformer(fn func(errs []shared.Error) []error) Option

WithErrorsTransformer returns an Option that sets the transformer for the Validator.

func WithFieldLocationNamingFn

func WithFieldLocationNamingFn(fn func(field fmap.Field) string) Option

WithFieldLocationNamingFn returns an Option that sets the field location naming function for the Validator.

func WithTranslator

func WithTranslator(t translator.Translator) Option

WithTranslator returns an Option that sets the translator for the Validator.

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

Validator holds validation rules of the configured types.

func New

func New(opts ...Option) *Validator

New creates a new Validator instance with default values for storage and helper. It also applies any options passed to the function to the new instance.

func (*Validator) Constraints added in v0.1.0

func (v *Validator) Constraints() []shared.Constraint

Constraints returns the rules of the configured structs that JSON Schema can express, see shared.Constraint, for the generators of the schemas of the API. The structs are sorted by their names, the rules are in the order of the configuration.

func (*Validator) GetHelper

func (v *Validator) GetHelper() shared.Helper

GetHelper returns the helper object associated with the Validator instance.

func (*Validator) Validate

func (v *Validator) Validate(ctx context.Context, obj any) []error

Validate is similar to ValidateTyped, but returns errors transformed by the errors transformer. It returns nil if there are no errors.

func (*Validator) ValidateTyped

func (v *Validator) ValidateTyped(ctx context.Context, obj any) []shared.Error

ValidateTyped validates obj using the rules configured for its type. obj is a pointer to the configured struct. A struct value is validated by a shallow copy: modifications like Trim of its direct fields are not visible to the caller, but values behind pointers and slice elements are shared with the caller and can be modified. It returns nil if there are no errors, no rules for the obj type or obj is a nil pointer.

Directories

Path Synopsis
integrations
echo module
gin module
goi18n module
huma module
internal
helper
Package helper builds the errors of the rules with the translated messages and the locations of the fields.
Package helper builds the errors of the rules with the translated messages and the locations of the fields.
tags
Package tags configures the rules of the tags of go-playground/validator by the rules of valigo.
Package tags configures the rules of the tags of go-playground/validator by the rules of valigo.
testenv
Package testenv describes the environment of the tests.
Package testenv describes the environment of the tests.
zero
Package zero allocates the pointer fields of the models of Configure, so the rules are configured by the pointers to the fields of the nested structs.
Package zero allocates the pointer fields of the models of Configure, so the rules are configured by the pointers to the fields of the nested structs.
Package problem writes validation errors as the problem details of RFC 9457 (RFC 7807 before it): application/problem+json with the errors of the fields.
Package problem writes validation errors as the problem details of RFC 9457 (RFC 7807 before it): application/problem+json with the errors of the fields.
rules
eq
Package eq configures the rules of comparable values: enums, bools, named types.
Package eq configures the rules of comparable values: enums, bools, named types.
num
str
timex
Package timex configures the rules of time.Time values: b.Field(&m.StartsAt).As(timex.Of).After(start).
Package timex configures the rules of time.Time values: b.Field(&m.StartsAt).As(timex.Of).After(start).
uuid module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL