validate

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2025 License: MIT Imports: 4 Imported by: 1

README

validate

Composable validation for Go with fluent builders, rule tags, struct validation, and optional message translation.

Packages

  • github.com/aatuh/validate: main API (Validate, builders)
  • github.com/aatuh/validate/validators: type-specific rules
  • github.com/aatuh/validate/errors: error types and codes
  • github.com/aatuh/validate/structvalidator: struct validation
  • github.com/aatuh/validate/translator: i18n helpers

Quick start

Basic validation
package main

import (
    "fmt"
    "github.com/aatuh/validate"
)

func main() {
    v := validate.New()

    // String: Email() is terminal and returns func(any) error.
    emailV := v.String().MinLength(3).MaxLength(50).Email()
    if err := emailV("user@example.com"); err != nil {
        fmt.Println("validation failed:", err)
    }

    // Int: call Build() to obtain func(any) error.
    ageV := v.Int().MinInt(18).MaxInt(120).Build()
    if err := ageV(25); err != nil {
        fmt.Println("validation failed:", err)
    }
}
Slice validation with element rules
v := validate.New()
// tags must be non-empty strings, at least 2 chars each
tagElem := v.String().MinLength(2).Build()
tagsV := v.Slice().MinSliceLength(1).ForEach(tagElem).Build()
if err := tagsV([]string{"go", "lib"}); err != nil {
    fmt.Println("validation failed:", err)
}
Struct validation
package main

import (
    "fmt"
    "github.com/aatuh/validate"
    verrs "github.com/aatuh/validate/errors"
    "github.com/aatuh/validate/structvalidator"
)

type User struct {
    Name  string `validate:"string;min=3;max=50"`
    Email string `validate:"string;email"`
    Age   int    `validate:"int;min=18;max=120"`
}

func main() {
    v := validate.New()
    sv := structvalidator.NewStructValidator(v)

    u := User{Name: "John Doe", Email: "john@example.com", Age: 25}
    if err := sv.ValidateStruct(u); err != nil {
        if es, ok := err.(verrs.Errors); ok {
            fmt.Println("errors:", es.AsMap())
        } else {
            fmt.Println("validation failed:", err)
        }
    }
}
With translation
package main

import (
    "fmt"
    "github.com/aatuh/validate"
    "github.com/aatuh/validate/translator"
)

func main() {
    msgs := map[string]string{
        "string.minLength": "doit contenir au moins %d caractères",
        "string.email.invalid": "adresse email invalide",
    }
    tr := translator.NewSimpleTranslator(msgs)

    v := validate.New().WithTranslator(tr)

    check := v.String().MinLength(5).Email()
    if err := check("ab"); err != nil {
        fmt.Println("fr:", err)
    }
}

Tip: translator.DefaultEnglishTranslations() provides sensible defaults.

API reference

Validate
v := validate.New()
v = v.WithTranslator(tr)
v = v.PathSeparator(".")

custom := map[string]func(any) error{
    "customRule": func(v any) error { return nil },
}
v2 := validate.NewWithCustomRules(custom)
Builders
// String
strV := v.String().MinLength(3).MaxLength(50).Regex(`^[a-z0-9_]+$`).Build()

// Int (accepts any Go int type at call time)
intV := v.Int().MinInt(0).MaxInt(100).Build()

// Int64 (requires exactly int64 at call time)
int64V := v.Int64().MinInt(0).MaxInt(100).Build()

// Slice
elem := v.String().MinLength(2).Build()
sliceV := v.Slice().MinSliceLength(1).ForEach(elem).Build()

// Bool
boolV := v.Bool() // type-check only
Struct tags
type Example struct {
    Name  string   `validate:"string;min=3;max=50"`
    Email string   `validate:"string;email"`
    Age   int      `validate:"int;min=18;max=120"`
    Tags  []string `validate:"slice;min=1;max=5"`
    Flag  bool     `validate:"bool"`
}

Supported tokens:

  • string: len, min, max, oneof=a b c, regex=..., email
  • int/int64: min, max (use int64;... to require int64)
  • slice: len, min, max
  • bool: type only
Errors

Struct validation returns errors.Errors which offers helpers:

if es, ok := err.(verrs.Errors); ok {
    _ = es.Has("Email")
    _ = es.Filter("") // or a nested prefix like "Address."
    _ = es.AsMap()
}

Note: direct builder calls usually return a single error, not an errors.Errors aggregate.

Error codes

Stable constants for programmatic handling (see errors/codes.go):

const (
    // String
    CodeStringMin = "string.min"
    CodeStringMax = "string.max"
    CodeStringNonEmpty = "string.nonempty"
    CodeStringPattern = "string.pattern"
    CodeStringOneOf = "string.oneof"

    // Number (ints/floats)
    CodeNumberMin = "number.min"
    CodeNumberMax = "number.max"

    // Slice
    CodeSliceMin = "slice.min"
    CodeSliceMax = "slice.max"
)

Documentation

Overview

Package validate provides composable validation helpers for Go with fluent builders, rule tags, and struct validation. It includes optional message translation support.

Package validate - opts.go Runtime options for struct validation and field path formatting.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CheckFunc added in v1.0.1

type CheckFunc func(v any) error

CheckFunc validates a single value and returns an error if invalid.

func WithoutContext added in v1.0.1

func WithoutContext(f CheckFuncCtx) CheckFunc

WithoutContext adapts a CheckFuncCtx to a CheckFunc by using context.Background(). Prefer passing through contexts in hot paths.

type CheckFuncCtx added in v1.0.1

type CheckFuncCtx func(ctx context.Context, v any) error

CheckFuncCtx is the context-aware variant of CheckFunc.

func WithContext added in v1.0.1

func WithContext(f CheckFunc) CheckFuncCtx

WithContext adapts a CheckFunc to a CheckFuncCtx that ignores ctx.

type IntBuilder added in v1.0.1

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

IntBuilder accumulates integer rules; Build() finishes it.

func (*IntBuilder) Build added in v1.0.1

func (b *IntBuilder) Build() func(any) error

Build returns a func(any) error that validates the provided value.

func (*IntBuilder) MaxInt added in v1.0.1

func (b *IntBuilder) MaxInt(n int64) *IntBuilder

func (*IntBuilder) MinInt added in v1.0.1

func (b *IntBuilder) MinInt(n int64) *IntBuilder

type SliceBuilder added in v1.0.1

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

SliceBuilder accumulates slice rules; Build() finishes it.

func (*SliceBuilder) Build added in v1.0.1

func (b *SliceBuilder) Build() func(any) error

func (*SliceBuilder) ForEach added in v1.0.1

func (b *SliceBuilder) ForEach(
	elem func(any) error,
) *SliceBuilder

ForEach applies an element validator to each item in the slice.

func (*SliceBuilder) Length added in v1.0.1

func (b *SliceBuilder) Length(n int) *SliceBuilder

func (*SliceBuilder) MaxSliceLength added in v1.0.1

func (b *SliceBuilder) MaxSliceLength(n int) *SliceBuilder

func (*SliceBuilder) MinSliceLength added in v1.0.1

func (b *SliceBuilder) MinSliceLength(n int) *SliceBuilder

type StringBuilder added in v1.0.1

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

StringBuilder accumulates string validation rules and can be finished with Build() or by calling a terminal rule (like Email()) which returns the final func(any) error.

func (*StringBuilder) Build added in v1.0.1

func (b *StringBuilder) Build() func(any) error

Build returns the composite validator func.

func (*StringBuilder) Email added in v1.0.1

func (b *StringBuilder) Email() func(any) error

Email is terminal for convenience in examples. It appends the rule and returns the finished validator func.

func (*StringBuilder) Length added in v1.0.1

func (b *StringBuilder) Length(n int) *StringBuilder

func (*StringBuilder) MaxLength added in v1.0.1

func (b *StringBuilder) MaxLength(n int) *StringBuilder

func (*StringBuilder) MinLength added in v1.0.1

func (b *StringBuilder) MinLength(n int) *StringBuilder

func (*StringBuilder) OneOf added in v1.0.1

func (b *StringBuilder) OneOf(vals ...string) *StringBuilder

func (*StringBuilder) Regex added in v1.0.1

func (b *StringBuilder) Regex(pat string) *StringBuilder

Regex is not terminal, allowing more chaining. Call Build() to finish.

type Validate

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

Validate is the main struct that holds custom validation rules and an optional translator.

func New added in v1.0.1

func New() *Validate

New creates a new Validate with sane defaults.

func NewWithCustomRules added in v1.0.1

func NewWithCustomRules(
	custom map[string]func(any) error,
) *Validate

NewWithCustomRules creates a new Validate with pre-registered rules.

func (*Validate) Bool added in v1.0.1

func (v *Validate) Bool() func(any) error

Bool returns a bool validator func (no rules yet, kept for symmetry).

func (*Validate) FromRules

func (v *Validate) FromRules(
	rules []string,
) (func(any) error, error)

FromRules creates a validator func from rule tokens. The first token is the type: "string", "int", "int64", "slice", "bool".

func (*Validate) Int added in v1.0.1

func (v *Validate) Int() *IntBuilder

Int returns a fluent integer validator builder that accepts any Go int type at call time.

func (*Validate) Int64 added in v1.0.1

func (v *Validate) Int64() *IntBuilder

Int64 returns a fluent builder that requires exactly int64.

func (*Validate) PathSeparator added in v1.0.1

func (v *Validate) PathSeparator(sep string) *Validate

PathSeparator customizes the separator used in nested field paths. Example: "User.Addresses[2].Zip".

func (*Validate) Slice added in v1.0.1

func (v *Validate) Slice() *SliceBuilder

Slice returns a fluent slice validator builder. It accepts any slice element type at call time.

func (*Validate) String added in v1.0.1

func (v *Validate) String() *StringBuilder

String returns a fluent string validator builder.

func (*Validate) WithTranslator

func (v *Validate) WithTranslator(
	t translator.Translator,
) *Validate

WithTranslator sets a Translator for localized error messages and returns the receiver for chaining.

type ValidateOpts added in v1.0.1

type ValidateOpts struct {
	// StopOnFirst makes validation fail fast on the first FieldError.
	// Default is false (aggregate all errors).
	StopOnFirst bool

	// PathSep sets the separator between nested field parts.
	// Example: "User.Addresses[2].Zip".
	// If empty, it will be taken from Validate (or "." if nil).
	PathSep string
}

ValidateOpts tunes validation behavior per call.

func ApplyOpts added in v1.0.1

func ApplyOpts(v *Validate, o ValidateOpts) ValidateOpts

ApplyOpts fills missing values using the given *Validate instance. If PathSep is empty, it uses v's separator, or "." when v is nil.

func (ValidateOpts) WithDefaults added in v1.0.1

func (o ValidateOpts) WithDefaults() ValidateOpts

WithDefaults currently does not change anything, but is kept to allow future option defaults without breaking callers.

Directories

Path Synopsis
Package errors provides error types and error handling utilities for validation.
Package errors provides error types and error handling utilities for validation.
Package structvalidator provides struct validation functionality using reflection.
Package structvalidator provides struct validation functionality using reflection.
Package translator provides internationalization support for validation messages.
Package translator provides internationalization support for validation messages.
Package validators provides type-specific validation functionality.
Package validators provides type-specific validation functionality.

Jump to

Keyboard shortcuts

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