valid

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2026 License: MIT Imports: 4 Imported by: 0

README

valid

Struct validation backed by go-playground/validator with structured error output.

Module: code.nochebuena.dev/go/valid Tier: 1 — depends on xerrors (Tier 0) and go-playground/validator/v10 Go: 1.25+ Dependencies: code.nochebuena.dev/go/xerrors, github.com/go-playground/validator/v10


Overview

valid wraps go-playground/validator/v10 and maps validation failures to structured *xerrors.Err values. It replaces the old check package, adding a plain constructor, a swappable message provider, and English messages by default.

Installation

go get code.nochebuena.dev/go/valid

Quick start

import "code.nochebuena.dev/go/valid"

type CreateUserRequest struct {
    Name  string `validate:"required"`
    Email string `validate:"required,email"`
    Age   int    `validate:"min=18,max=120"`
}

v := valid.New()

err := v.Struct(req)
if err != nil {
    // err is a *xerrors.Err with code ErrInvalidInput.
    var xe *xerrors.Err
    if errors.As(err, &xe) {
        fmt.Println(xe.Code())        // INVALID_ARGUMENT
        fmt.Println(xe.Message())     // "field 'Email' must be a valid email address"
        fmt.Println(xe.Fields())      // map[field:Email tag:email]
    }
}

Usage

Creating a validator
// English messages (default).
v := valid.New()

// Spanish messages.
v := valid.New(valid.WithMessageProvider(valid.SpanishMessages))

// Custom message provider.
v := valid.New(valid.WithMessageProvider(myProvider))
Validating structs
err := v.Struct(myStruct)
Outcome Error returned
All fields pass nil
Field constraint failure *xerrors.Err with ErrInvalidInput, first error only
Not a struct *xerrors.Err with ErrInternal

The returned *xerrors.Err for field failures carries:

  • Fields()["field"] — the failing struct field name
  • Fields()["tag"] — the failing validation rule (e.g. "email", "required")
  • Unwrap() — the underlying validator.ValidationErrors
Message providers

MessageProvider maps a validation failure to a human-readable message:

type MessageProvider interface {
    Message(field, tag, param string) string
}

Built-in presets:

Variable Language Usage
DefaultMessages English automatic (no option needed)
SpanishMessages Spanish WithMessageProvider(valid.SpanishMessages)

Custom provider example:

type myMessages struct{}

func (m myMessages) Message(field, tag, param string) string {
    switch tag {
    case "required":
        return field + " is mandatory"
    default:
        return field + " failed: " + tag
    }
}

v := valid.New(valid.WithMessageProvider(myMessages{}))

Design decisions

No singletonvalid.New(opts...) returns a plain value. Multiple validators with different configurations can coexist. Tests create isolated instances without global state.

Only the first validation error is surfacedgo-playground/validator returns all field errors at once; we surface only the first for API simplicity. Apps needing all failures can cast errors.Unwrap(err) to validator.ValidationErrors:

var xe *xerrors.Err
errors.As(err, &xe)

var ve validator.ValidationErrors
errors.As(errors.Unwrap(xe), &ve) // all field errors

valid imports xerrors directlyvalid is Tier 1 and xerrors is Tier 0. The import is intentional; valid constructs *xerrors.Err values. Duck-typing is reserved for cases where the import would create a circular or cross-tier dependency.

Spanish is bundled, not a separate module — the Spanish preset is a small, zero-dep addition. Splitting it into a separate module would add publish overhead for negligible gain.

Ecosystem

Tier 0:   xerrors
               ↑ (direct import — constructs *xerrors.Err)
Tier 1:   valid ← you are here
               ↑
Tier 2:   httputil (injects valid.Validator into generic handler)

License

MIT

Documentation

Overview

Package valid provides struct validation backed by github.com/go-playground/validator/v10.

Create a validator with New:

v := valid.New()

Validate a struct:

type CreateUserRequest struct {
    Name  string `validate:"required"`
    Email string `validate:"required,email"`
    Age   int    `validate:"min=18,max=120"`
}

err := v.Struct(req)
if err != nil {
    // err is a *xerrors.Err with code ErrInvalidInput.
    // Use errors.As to inspect it.
}

Use Spanish messages:

v := valid.New(valid.WithMessageProvider(valid.SpanishMessages))

Use a custom message provider:

type myMessages struct{}
func (m myMessages) Message(field, tag, param string) string { ... }

v := valid.New(valid.WithMessageProvider(myMessages{}))

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MessageProvider

type MessageProvider interface {
	Message(field, tag, param string) string
}

MessageProvider maps a validation failure to a human-readable message.

  • field: the struct field name (e.g. "Email")
  • tag: the failing validation rule (e.g. "required", "email", "min")
  • param: the rule parameter if any (e.g. "18" for min=18), or "" if none
var DefaultMessages MessageProvider = defaultMessages{}

DefaultMessages is the built-in English message provider. Used automatically when no WithMessageProvider option is given.

var SpanishMessages MessageProvider = spanishMessages{}

SpanishMessages is an opt-in Spanish message provider.

type Option

type Option func(*config)

Option configures a Validator.

func WithMessageProvider

func WithMessageProvider(mp MessageProvider) Option

WithMessageProvider sets a custom MessageProvider. Default: DefaultMessages (English).

type Validator

type Validator interface {
	// Struct validates v and returns a *xerrors.Err if validation fails.
	// Returns nil if v is valid.
	// Returns ErrInvalidInput for field constraint failures (first error only).
	// Returns ErrInternal if v is not a struct.
	Struct(v any) error
}

Validator validates structs using struct tags.

func New

func New(opts ...Option) Validator

New returns a Validator. Without options, DefaultMessages (English) is used.

Jump to

Keyboard shortcuts

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