validation

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: MIT Imports: 16 Imported by: 0

README

GoForj validation gopher with a checklist

Typed fluent validation with reusable rules and useful field errors.

Go Reference MIT License CI Security Go 1.24 or newer Version v0.1.0 Measured unit coverage Executed Go tests

Keep field names, values, and constraints together. Validate decoded requests, configuration, and domain values using ordinary Go code, with no runtime dependencies.

Feature What it provides
 Typed chains Typed builders for strings, numbers, booleans, time, and collections.
 Reusable rules Compose rules and plug in custom validators without global registration.
 Format checks Common formats and character checks directly in the fluent chain.
 Field errors Ordered paths, stable codes, custom messages, and localization hooks.
 Optional inputs Distinguish omitted fields, explicit null, and supplied zero values.

Quick start

Requires Go 1.24 or newer.

go get github.com/goforj/validation@v0.1.0

The complete registration program defines the Registration model and imports the library:

req := Registration{
	Name:  "Ada",
	Email: "ada@example.com",
	Age:   36,
	Terms: true,
}
err := validation.Validate(
	validation.String("name", req.Name).Required().Min(2).Max(100),
	validation.String("email", req.Email).Required().IsEmail(),
	validation.Number("age", req.Age).Min(18),
	validation.Bool("terms", req.Terms).Accepted(),
)
fmt.Println(err)
// <nil>

How it works

  • Values are explicit. Zero and false are ordinary values. Rules evaluate empty strings unless you use a lazy condition to omit a field. Required checks run before content checks.
  • Errors stay useful. Validation collects the first violation per field by default. Use New().CollectAll() for all content failures or StopOnFirstError() to stop globally. Custom messages retain their machine code. Unexpected rule errors abort evaluation and remain operational errors.
  • Custom rules fit the same chain. Implement Rule[T] with Validate(T) error, or use a function adapter. Return validation.Invalid for an input failure. Add RuleWithContext[T] for dependencies that need cancellation.
  • Evaluation is local. Builders can be branched and reused. Input slices and application dependencies are borrowed. Coordinate concurrent mutation in your application.

See validation contracts for presence, formats, paths, configuration errors, ownership, and cancellation.

Runnable examples

Run from the repository root with go run ./examples/<name>. Tests verify every program's output.

quickstart · formats · patch · nested · custom · context · domain · errors · constraints · advanced · time · presence · moreformats · policies

API index

Group Functions
Values String · Number · Bool · Validate
Formats IsEmail · IsURL · IsUUID · IsUUIDv4 · IsUUIDv7 · IsIP · IsIPv4 · IsIPv6 · IsJSON · IsBase64
Conditions When
Collections Group · Slice · Each
Custom rules Using · Invalid
Context ValidateContext · Check
Domain values Value · RuleFunc · ContextRuleFunc
Errors Label · Message · First · Messages · Issues
Constraints Required · RequiredIf · NotBlank · Min · Max · In · Equal · Match · Accepted
Text constraints Len · Contains · NotContains · StartsWith · EndsWith · NotEqual · NotIn
Numeric constraints GreaterThan · LessThan · MultipleOf
Collection constraints Map · Unique · UniqueBy · HasKey · OnlyKeys
Dates and times Time · Before · After · IsDate · IsDateIn
Optional inputs Presence · Nullable · Optional · Provided · Null · IsPresent · IsNull · Get
More formats IsULID · IsHostname · IsCIDR · IsMAC · IsE164 · IsBase64URL · IsAlpha · IsAlphanumeric · IsDigits · IsASCII · IsLowercase · IsUppercase · IsUTF8
Composition Any · All · Not
Evaluation policy New · CollectAll · StopOnFirstError · FormatMessages

Values

String · Number · Bool · Validate

String starts a deferred chain for a borrowed application value.

req := Registration{
	Name:  "Ada",
	Email: "ada@example.com",
	Age:   36,
	Terms: true,
}
err := validation.Validate(
	validation.String("name", req.Name).Required().Min(2).Max(100),
	validation.String("email", req.Email).Required().IsEmail(),
	validation.Number("age", req.Age).Min(18),
	validation.Bool("terms", req.Terms).Accepted(),
)
fmt.Println(err)
// <nil>

Formats

IsEmail · IsURL · IsUUID · IsUUIDv4 · IsUUIDv7 · IsIP · IsIPv4 · IsIPv6 · IsJSON · IsBase64

IsEmail requires a bare ASCII mailbox with a dotted domain.

err := validation.Validate(
	validation.String("email", "ada@example.com").IsEmail(),
	validation.String("site", "https://goforj.dev").IsURL(),
	validation.String("id", "550e8400-e29b-41d4-a716-446655440000").IsUUID(),
	validation.String("trace_id", "550e8400-e29b-41d4-a716-446655440000").IsUUIDv4(),
	validation.String("request_id", "0190bde7-5ad0-7000-8000-000000000001").IsUUIDv7(),
	validation.String("host", "::1").IsIP(),
	validation.String("ip", "192.0.2.1").IsIPv4(),
	validation.String("ipv6", "2001:db8::1").IsIPv6(),
	validation.String("metadata", `{"source":"web"}`).IsJSON(),
	validation.String("cursor", "YWJj").IsBase64(),
)
fmt.Println(err)
// <nil>

Conditions

When

When evaluates the callback lazily only when condition is true.

return validation.Validate(
	validation.When(req.Email != nil, func() validation.Field {
		return validation.String("email", *req.Email).Required().IsEmail()
	}),
)

Collections

Group · Slice · Each

Group prefixes child paths with a literal parent label.

items := []Item{
	{SKU: "book", Quantity: 0},
}
err := validation.Validate(
	validation.Group("address", validation.String("city", "").Required()),
	validation.Slice("items", items).Required().Max(100).
		Each(func(item Item) []validation.Field {
			return []validation.Field{
				validation.String("sku", item.SKU).Required(),
				validation.Number("quantity", item.Quantity).Min(1),
			}
		}),
)
failures := err.(*validation.Errors)
for _, issue := range failures.Issues() {
	fmt.Println(issue.Path, issue.Code)
}
// address.city required
// items.0.quantity min

Custom rules

Using · Invalid

Using attaches a reusable validator for the exact value type.

// AllowedDomain restricts registrations to a configured company domain.
type AllowedDomain struct {
	Domain string
}

// Validate returns a safe input failure for addresses outside the company.
func (r AllowedDomain) Validate(value string) error {
	_, domain, ok := strings.Cut(value, "@")
	if !ok || !strings.EqualFold(domain, r.Domain) {
		return validation.Invalid("email_domain", "Use your company email address.")
	}
	return nil
}

err := validation.Validate(
	validation.String("email", "ada@other.example").Required().IsEmail().
		Using(AllowedDomain{Domain: "goforj.dev"}),
)
fmt.Println(err)
// Use your company email address.

Context

ValidateContext · Check

ValidateContext evaluates with request cancellation and the configured collection policy.

unavailable := errors.New("directory unavailable")
err := validation.ValidateContext(context.Background(),
	validation.String("email", "ada@example.com").IsEmail().
		Check(func(ctx context.Context, email string) error {
			// A real directory client would use ctx and email here.
			return unavailable
		}),
)
fmt.Println(errors.Is(err, unavailable))
// true

Domain values

Value · RuleFunc · ContextRuleFunc

Value starts a deferred chain for a borrowed application value.

window := validation.RuleFunc[Delivery](func(value Delivery) error {
	if value.Days > 30 {
		return validation.Invalid("delivery_window", "Choose delivery within 30 days.")
	}
	return nil
})
available := validation.ContextRuleFunc[Delivery](func(ctx context.Context, value Delivery) error {
	return ctx.Err()
})
err := validation.Validate(
	validation.Value("delivery", Delivery{Days: 7}).Using(window).Using(available),
)
fmt.Println(err)
// <nil>

Errors

Label · Message · First · Messages · Issues

Label sets the human-readable field name without changing its output path.

err := validation.Validate(
	validation.String("email", "bad").Label("email address").IsEmail().
		Message("Enter your work email address."),
)
var failures *validation.Errors
if errors.As(err, &failures) {
	fmt.Println(failures.First("email"))
	// Enter your work email address.
	fmt.Println(failures.Messages()["email"])
	// [Enter your work email address.]
	fmt.Println(failures.Issues()[0].Code)
	// email
}

Constraints

Required · RequiredIf · NotBlank · Min · Max · In · Equal · Match · Accepted

Required rejects an empty string before content rules run.

err := validation.Validate(
	validation.String("name", "Ada").Required().NotBlank().Min(2).Max(100),
	validation.String("company", "").RequiredIf(false).Max(200),
	validation.String("role", "member").In("member", "admin"),
	validation.String("confirmation", "correct horse").Equal("correct horse"),
	validation.String("sku", "BOOK-42").Match(regexp.MustCompile(`^[A-Z]+-\d+$`)),
	validation.Number("age", 36).Min(18).Max(120),
	validation.Bool("terms", true).Accepted(),
)
fmt.Println(err)
// <nil>

Text constraints

Len · Contains · NotContains · StartsWith · EndsWith · NotEqual · NotIn

Len requires exactly length Unicode code points.

err := validation.Validate(
	validation.String("sku", "BOOK-42").Len(7).Contains("-").NotContains(" ").StartsWith("BOOK").EndsWith("42"),
	validation.String("username", "ada").NotEqual("root").NotIn("admin", "system"),
)
fmt.Println(err)
// <nil>

Numeric constraints

GreaterThan · LessThan · MultipleOf

GreaterThan requires a strict lower bound in the field's numeric type.

err = validation.Validate(
	validation.Number("quantity", 12).GreaterThan(0).LessThan(100).MultipleOf(3),
)
fmt.Println(err)
// <nil>

Collection constraints

Map · Unique · UniqueBy · HasKey · OnlyKeys

Map starts a deferred chain for a borrowed string-keyed map.

err = validation.Validate(
	validation.Slice("tags", []string{"go", "books"}).Unique().Contains("go"),
	validation.Slice("products", []Product{{ID: 1}, {ID: 2}}).
		Using(validation.UniqueBy(func(product Product) int { return product.ID })),
	validation.Map("labels", map[string]string{"category": "books"}).
		Required().HasKey("category").OnlyKeys("category").
		Each(func(key, value string) []validation.Field {
			return []validation.Field{validation.String("", value).NotBlank()}
		}),
)
fmt.Println(err)
// <nil>

Dates and times

Time · Before · After · IsDate · IsDateIn

Time starts a deferred chain using instant comparisons across time zones.

starts := time.Date(2026, 11, 10, 10, 0, 0, 0, time.UTC)
ends := starts.Add(2 * time.Hour)
fmt.Println(validation.Validate(
	validation.Time("starts_at", starts).Required().Before(ends).Min(starts).Max(ends).Equal(starts),
	validation.Time("ends_at", ends).After(starts),
	validation.String("date", "2026-11-10").IsDate(time.DateOnly),
	validation.String("local_time", "2026-11-10 10:00").IsDateIn("2006-01-02 15:04", time.UTC),
))
// <nil>

Optional inputs

Presence · Nullable · Optional · Provided · Null · IsPresent · IsNull · Get

Presence defers child validation until input contains a non-null value. Use an empty child path to retain path, or a named child to append a segment.

// nonBlank shares a content rule across optional and presence-aware inputs.
func nonBlank(value string) validation.Field { return validation.String("", value).NotBlank() }

var patch struct {
	Seats validation.Input[int]    `json:"seats,omitzero"`
	Name  validation.Input[string] `json:"name,omitzero"`
}
fmt.Println(json.Unmarshal([]byte(`{"seats":0,"name":null}`), &patch))
// <nil>
fmt.Println(validation.Validate(
	validation.Presence("seats", patch.Seats, func(v int) validation.Field {
		return validation.Number("", v).Min(0)
	}).Required(),
	validation.Presence("name", patch.Name, nonBlank).Nullable(),
))
// <nil>
fmt.Println(patch.Seats.IsPresent(), patch.Name.IsNull())
// true true
value, ok := validation.Provided(false).Get()
fmt.Println(value, ok, validation.Null[string]().IsNull())
// false true true
var nickname *string
fmt.Println(validation.Validate(validation.Optional(nickname, nonBlank)))
// <nil>
name := "Ada"
fmt.Println(validation.Validate(
	validation.Optional(&name, nonBlank),
	validation.Presence("name", validation.Provided(name), nonBlank),
))
// <nil>

More formats

IsULID · IsHostname · IsCIDR · IsMAC · IsE164 · IsBase64URL · IsAlpha · IsAlphanumeric · IsDigits · IsASCII · IsLowercase · IsUppercase · IsUTF8

IsULID requires a case-insensitive 128-bit ULID.

fmt.Println(validation.Validate(
	validation.String("id", "01ARZ3NDEKTSV4RRFFQ69G5FAV").IsULID(),
	validation.String("host", "api.example.com").IsHostname(),
	validation.String("network", "192.0.2.0/24").IsCIDR(),
	validation.String("device", "00:11:22:33:44:55").IsMAC(),
	validation.String("phone", "+14155552671").IsE164(),
	validation.String("token", "__8").IsBase64URL(),
	validation.String("name", "Ada").IsAlpha(),
	validation.String("sku", "A123").IsAlphanumeric(),
	validation.String("pin", "012345").IsDigits(),
	validation.String("key", "header_name").IsASCII(),
	validation.String("slug", "café").IsLowercase(),
	validation.String("code", "ÉCOLE").IsUppercase(),
	validation.String("title", "こんにちは").IsUTF8(),
))
// <nil>

Composition

Any · All · Not

Any accepts a value when a rule succeeds; operational errors abort evaluation.

startsA := validation.RuleFunc[string](func(v string) error {
	if strings.HasPrefix(v, "A") {
		return nil
	}
	return validation.Invalid("starts_a", "Must start with A")
})
endsZ := validation.ContextRuleFunc[string](func(_ context.Context, v string) error {
	if strings.HasSuffix(v, "Z") {
		return nil
	}
	return validation.Invalid("ends_z", "Must end with Z")
})
fmt.Println(validation.Validate(
	validation.String("code", "ABC").Using(validation.All(
		validation.Any[string](startsA, endsZ),
		validation.Not[string](endsZ),
	)),
))
// <nil>
fmt.Println(validation.Validate(
	validation.String("code", "XYZ").Using(validation.Any[string](startsA, endsZ)),
))
// <nil>

Evaluation policy

New · CollectAll · StopOnFirstError · FormatMessages

New creates a validator with first-violation-per-field collection and default messages.

validator := validation.New().CollectAll().FormatMessages(func(issue validation.Issue) string {
	return issue.Path + ": " + issue.Code
})
var failures *validation.Errors
if err := validator.Validate(
	validation.String("name", "a").Min(3).Contains("z"),
); errors.As(err, &failures) {
	fmt.Println(failures.Messages()["name"])
	// [name: min name: contains]
}
first := validator.StopOnFirstError()
fmt.Println(first.ValidateContext(
	context.Background(),
	validation.String("name", "").Required(),
	validation.Number("age", 0).Min(18),
))
// name: required

Development

make test
make test-race
make vet
make test-coverage
make generate
make check-generated

The root module contains the library and executable examples. The separate docs module contains documentation tooling. See development for checks and validation contracts for API behavior.

The initial release review records the review passes, fixes, and verification evidence.

Documentation

Overview

Package validation provides typed, fluent validation of application values. Rules run only during Validate or ValidateContext. Evaluation collects the first violation per field by default, in declaration order. Validator configures broader collection, global stopping, and message formatting. Unexpected rule errors abort evaluation and remain operational errors rather than client-facing messages.

Builders can be branched and reused without sharing evaluation state. Slices and application dependencies are borrowed; callers must not mutate inputs during evaluation and must coordinate any state used by custom rules.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Validate

func Validate(fields ...Field) error

Validate evaluates fields sequentially with a background context.

func ValidateContext

func ValidateContext(ctx context.Context, fields ...Field) error

ValidateContext collects field violations while giving operational errors precedence.

Types

type BoolField

type BoolField[T ~bool] struct {
	// contains filtered or unexported fields
}

BoolField is an immutable fluent chain for bool values.

func Bool

func Bool[T ~bool](path string, value T) BoolField[T]

Bool starts a deferred chain for a borrowed application value.

func (BoolField[T]) Accepted

func (b BoolField[T]) Accepted() BoolField[T]

Accepted requires true while ordinary boolean checks continue to accept false.

func (BoolField[T]) Check

func (b BoolField[T]) Check(check func(context.Context, T) error) BoolField[T]

Check attaches a context-aware application check.

func (BoolField[T]) Equal

func (b BoolField[T]) Equal(other T) BoolField[T]

Equal requires the supplied boolean value.

func (BoolField[T]) Label

func (b BoolField[T]) Label(label string) BoolField[T]

Label sets the human-readable field name without changing its output path.

func (BoolField[T]) Message

func (b BoolField[T]) Message(message string) BoolField[T]

Message overrides the preceding rule message while preserving its code.

func (BoolField[T]) Using

func (b BoolField[T]) Using(rule Rule[T]) BoolField[T]

Using attaches a reusable validator for the exact value type.

type ConfigurationError

type ConfigurationError struct {
	Path    string
	Problem string
}

ConfigurationError identifies a malformed chain or rule rather than invalid input.

func (*ConfigurationError) Error

func (e *ConfigurationError) Error() string

Error describes the invalid rule configuration without printing submitted values.

type ContextRuleFunc

type ContextRuleFunc[T any] func(context.Context, T) error

ContextRuleFunc adapts a context-aware function into a reusable typed rule.

func (ContextRuleFunc[T]) Validate

func (f ContextRuleFunc[T]) Validate(value T) error

Validate evaluates the rule with a background context.

func (ContextRuleFunc[T]) ValidateContext

func (f ContextRuleFunc[T]) ValidateContext(ctx context.Context, value T) error

ValidateContext forwards the caller's context to the adapted function.

type Errors

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

Errors contains ordered field failures and supports errors.As.

func (*Errors) Error

func (e *Errors) Error() string

Error returns field messages in declaration order.

func (*Errors) First

func (e *Errors) First(path string) string

First returns the first message at path, or an empty string if none exists.

func (*Errors) Issues

func (e *Errors) Issues() []Issue

Issues returns ordered copies of issues and their constraint parameters.

func (*Errors) Messages

func (e *Errors) Messages() map[string][]string

Messages returns an independent field-to-messages map for form or API responses.

type Field

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

Field is a deferred validation operation constructed by a typed builder or group.

func Group

func Group(path string, fields ...Field) Field

Group prefixes child paths with a literal parent label.

func Optional

func Optional[T any](value *T, build func(T) Field) Field

Optional skips nil pointers and builds validation lazily for non-nil values.

func When

func When(condition bool, makeField func() Field) Field

When evaluates the callback lazily only when condition is true.

type Input

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

Input preserves whether JSON supplied a value, null, or no property at all. Its zero value is absent; use json's omitzero option to omit absent properties. Decoding T uses json.Unmarshal, so enclosing decoder options do not propagate.

func Null

func Null[T any]() Input[T]

Null constructs an explicitly null input.

func Provided

func Provided[T any](value T) Input[T]

Provided constructs an input containing a supplied value, including zero values.

func (Input[T]) Get

func (i Input[T]) Get() (T, bool)

Get returns the supplied value and reports whether it is present and non-null.

func (Input[T]) IsNull

func (i Input[T]) IsNull() bool

IsNull reports whether a supplied property was explicitly null.

func (Input[T]) IsPresent

func (i Input[T]) IsPresent() bool

IsPresent reports whether a property was supplied, including explicit null.

func (Input[T]) IsZero

func (i Input[T]) IsZero() bool

IsZero lets encoding/json omit absent properties with omitzero.

func (Input[T]) MarshalJSON

func (i Input[T]) MarshalJSON() ([]byte, error)

MarshalJSON emits null for absent or null inputs and otherwise encodes the value.

func (*Input[T]) UnmarshalJSON

func (i *Input[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON replaces the input only after a complete successful decode.

type Issue

type Issue struct {
	Path       string            `json:"path"`
	Code       string            `json:"code"`
	Message    string            `json:"message"`
	Parameters map[string]string `json:"parameters,omitempty"`
}

Issue describes a failed field without retaining its submitted value.

type MapField

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

MapField validates a borrowed string-keyed map with deterministic child paths.

func Map

func Map[T any](path string, value map[string]T) MapField[T]

Map starts a deferred chain for a borrowed string-keyed map.

func (MapField[T]) Check

func (b MapField[T]) Check(check func(context.Context, map[string]T) error) MapField[T]

Check attaches a context-aware application validator for the map.

func (MapField[T]) Each

func (b MapField[T]) Each(fields func(string, T) []Field) MapField[T]

Each constructs key and value checks in sorted key order after parent constraints pass.

func (MapField[T]) HasKey

func (b MapField[T]) HasKey(key string) MapField[T]

HasKey requires a literal key without exposing it in failure messages.

func (MapField[T]) Label

func (b MapField[T]) Label(label string) MapField[T]

Label changes human-readable prose without changing map paths.

func (MapField[T]) Len

func (b MapField[T]) Len(length int) MapField[T]

Len requires exactly length entries.

func (MapField[T]) Max

func (b MapField[T]) Max(max int) MapField[T]

Max permits at most max entries.

func (MapField[T]) Message

func (b MapField[T]) Message(message string) MapField[T]

Message customizes the preceding parent constraint while preserving its code.

func (MapField[T]) Min

func (b MapField[T]) Min(min int) MapField[T]

Min requires at least min entries.

func (MapField[T]) OnlyKeys

func (b MapField[T]) OnlyKeys(keys ...string) MapField[T]

OnlyKeys permits only the listed keys, copying configuration independently of the caller.

func (MapField[T]) Required

func (b MapField[T]) Required() MapField[T]

Required rejects nil and empty maps before content checks.

func (MapField[T]) RequiredIf

func (b MapField[T]) RequiredIf(condition bool) MapField[T]

RequiredIf enforces a nonempty map only when condition is true.

func (MapField[T]) Using

func (b MapField[T]) Using(rule Rule[map[string]T]) MapField[T]

Using attaches an application validator for the complete map value.

type NumberField

type NumberField[T Numeric] struct {
	// contains filtered or unexported fields
}

NumberField is an immutable fluent chain for number values.

func Number

func Number[T Numeric](path string, value T) NumberField[T]

Number starts a deferred chain for a borrowed application value.

func (NumberField[T]) Check

func (b NumberField[T]) Check(check func(context.Context, T) error) NumberField[T]

Check attaches a context-aware application check.

func (NumberField[T]) Equal

func (b NumberField[T]) Equal(other T) NumberField[T]

Equal requires the other value without exposing it in error messages.

func (NumberField[T]) GreaterThan

func (b NumberField[T]) GreaterThan(other T) NumberField[T]

GreaterThan requires a strict lower bound in the field's numeric type.

func (NumberField[T]) In

func (b NumberField[T]) In(values ...T) NumberField[T]

In permits only finite listed values and owns its constraint slice.

func (NumberField[T]) Label

func (b NumberField[T]) Label(label string) NumberField[T]

Label sets the human-readable field name without changing its output path.

func (NumberField[T]) LessThan

func (b NumberField[T]) LessThan(other T) NumberField[T]

LessThan requires a strict upper bound in the field's numeric type.

func (NumberField[T]) Max

func (b NumberField[T]) Max(max T) NumberField[T]

Max requires an inclusive upper bound in the field's exact numeric type.

func (NumberField[T]) Message

func (b NumberField[T]) Message(message string) NumberField[T]

Message overrides the preceding rule message while preserving its code.

func (NumberField[T]) Min

func (b NumberField[T]) Min(min T) NumberField[T]

Min requires an inclusive lower bound in the field's exact numeric type.

func (NumberField[T]) MultipleOf

func (b NumberField[T]) MultipleOf(divisor T) NumberField[T]

MultipleOf requires an exact remainder of zero; floats use binary math.Mod semantics.

func (NumberField[T]) NotEqual

func (b NumberField[T]) NotEqual(other T) NumberField[T]

NotEqual rejects the other finite value without exposing it in errors.

func (NumberField[T]) NotIn

func (b NumberField[T]) NotIn(values ...T) NumberField[T]

NotIn rejects the finite listed values and owns its constraint slice.

func (NumberField[T]) Using

func (b NumberField[T]) Using(rule Rule[T]) NumberField[T]

Using attaches a reusable validator for the exact value type.

type Numeric

type Numeric interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
}

Numeric permits all Go integer and floating-point types, including defined types.

type PresenceField

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

PresenceField validates an Input while preserving omitted and explicit-null states.

func Presence

func Presence[T any](path string, input Input[T], build func(T) Field) PresenceField[T]

Presence defers child validation until input contains a non-null value. Use an empty child path to retain path, or a named child to append a segment.

func (PresenceField[T]) Label

func (b PresenceField[T]) Label(label string) PresenceField[T]

Label sets the human-readable name for presence failures.

func (PresenceField[T]) Message

func (b PresenceField[T]) Message(message string) PresenceField[T]

Message overrides the preceding presence rule message while preserving its code.

func (PresenceField[T]) Nullable

func (b PresenceField[T]) Nullable() PresenceField[T]

Nullable permits explicit null without constructing child validation.

func (PresenceField[T]) Required

func (b PresenceField[T]) Required() PresenceField[T]

Required requires a supplied, non-null value; zero values remain valid.

func (PresenceField[T]) RequiredIf

func (b PresenceField[T]) RequiredIf(condition bool) PresenceField[T]

RequiredIf requires a supplied, non-null value when condition is true.

type Rule

type Rule[T any] interface {
	// Validate returns nil, an explicit Violation, or an operational error.
	Validate(value T) error
}

Rule validates a value using application-owned configuration and dependencies.

func All

func All[T any](rules ...Rule[T]) Rule[T]

All requires every rule, returning the first violation or operational error.

func Any

func Any[T any](rules ...Rule[T]) Rule[T]

Any accepts a value when a rule succeeds; operational errors abort evaluation.

func Not

func Not[T any](rule Rule[T]) Rule[T]

Not inverts a rule's input-validity result while preserving operational errors.

func UniqueBy

func UniqueBy[T any, K comparable](key func(T) K) Rule[[]T]

UniqueBy requires distinct comparable keys without retaining keys in failures.

type RuleFunc

type RuleFunc[T any] func(T) error

RuleFunc adapts an ordinary function into a reusable typed rule.

func (RuleFunc[T]) Validate

func (f RuleFunc[T]) Validate(value T) error

Validate evaluates the adapted function.

type RuleWithContext

type RuleWithContext[T any] interface {
	Rule[T]
	// ValidateContext uses the evaluation context for dependent operations.
	ValidateContext(ctx context.Context, value T) error
}

RuleWithContext propagates request cancellation to dependent operations.

type SliceField

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

SliceField is an immutable fluent chain for slice values.

func Slice

func Slice[T any](path string, value []T) SliceField[T]

Slice starts a deferred chain for a borrowed application value.

func (SliceField[T]) Check

func (b SliceField[T]) Check(check func(context.Context, []T) error) SliceField[T]

Check attaches a context-aware application check.

func (SliceField[T]) Contains

func (b SliceField[T]) Contains(target T) SliceField[T]

Contains requires an element equal under reflect.DeepEqual; the target value is borrowed.

func (SliceField[T]) Each

func (b SliceField[T]) Each(fields func(T) []Field) SliceField[T]

Each lazily constructs child fields for each element after parent checks pass.

func (SliceField[T]) Label

func (b SliceField[T]) Label(label string) SliceField[T]

Label sets the human-readable field name without changing its output path.

func (SliceField[T]) Len

func (b SliceField[T]) Len(length int) SliceField[T]

Len requires exactly length elements.

func (SliceField[T]) Max

func (b SliceField[T]) Max(max int) SliceField[T]

Max permits at most max elements.

func (SliceField[T]) Message

func (b SliceField[T]) Message(message string) SliceField[T]

Message overrides the preceding rule message while preserving its code.

func (SliceField[T]) Min

func (b SliceField[T]) Min(min int) SliceField[T]

Min requires at least min elements.

func (SliceField[T]) NotContains

func (b SliceField[T]) NotContains(target T) SliceField[T]

NotContains rejects an element equal under reflect.DeepEqual; the target value is borrowed.

func (SliceField[T]) Required

func (b SliceField[T]) Required() SliceField[T]

Required rejects empty and nil slices before evaluating child fields.

func (SliceField[T]) RequiredIf

func (b SliceField[T]) RequiredIf(condition bool) SliceField[T]

RequiredIf applies a nonempty constraint only when condition is true.

func (SliceField[T]) Unique

func (b SliceField[T]) Unique() SliceField[T]

Unique requires distinct Go-comparable elements; use UniqueBy for structs with slices or maps.

func (SliceField[T]) Using

func (b SliceField[T]) Using(rule Rule[[]T]) SliceField[T]

Using attaches a reusable validator for the exact value type.

type StringField

type StringField[T ~string] struct {
	// contains filtered or unexported fields
}

StringField is an immutable fluent chain for string values.

func String

func String[T ~string](path string, value T) StringField[T]

String starts a deferred chain for a borrowed application value.

func (StringField[T]) Check

func (b StringField[T]) Check(check func(context.Context, T) error) StringField[T]

Check attaches a context-aware application check.

func (StringField[T]) Contains

func (b StringField[T]) Contains(text string) StringField[T]

Contains requires the configured substring without modifying case or whitespace.

func (StringField[T]) EndsWith

func (b StringField[T]) EndsWith(suffix string) StringField[T]

EndsWith requires a literal suffix.

func (StringField[T]) Equal

func (b StringField[T]) Equal(other T) StringField[T]

Equal requires the other value without retaining it in failure details.

func (StringField[T]) In

func (b StringField[T]) In(values ...T) StringField[T]

In permits only the given values and owns a copy of their slice.

func (StringField[T]) IsASCII

func (b StringField[T]) IsASCII() StringField[T]

IsASCII requires nonempty ASCII text, including control bytes.

func (StringField[T]) IsAlpha

func (b StringField[T]) IsAlpha() StringField[T]

IsAlpha requires nonempty ASCII letters.

func (StringField[T]) IsAlphanumeric

func (b StringField[T]) IsAlphanumeric() StringField[T]

IsAlphanumeric requires nonempty ASCII letters and digits.

func (StringField[T]) IsBase64

func (b StringField[T]) IsBase64() StringField[T]

IsBase64 requires strict standard padded Base64 without whitespace.

func (StringField[T]) IsBase64URL

func (b StringField[T]) IsBase64URL() StringField[T]

IsBase64URL requires strict padded or raw URL-safe Base64.

func (StringField[T]) IsCIDR

func (b StringField[T]) IsCIDR() StringField[T]

IsCIDR requires an IP prefix without normalizing host bits.

func (StringField[T]) IsDate

func (b StringField[T]) IsDate(layout string) StringField[T]

IsDate requires a value parseable with a Go time layout, using UTC for unzoned input.

func (StringField[T]) IsDateIn

func (b StringField[T]) IsDateIn(layout string, location *time.Location) StringField[T]

IsDateIn interprets unzoned input in location without changing the supplied string.

func (StringField[T]) IsDigits

func (b StringField[T]) IsDigits() StringField[T]

IsDigits requires nonempty ASCII decimal digits.

func (StringField[T]) IsE164

func (b StringField[T]) IsE164() StringField[T]

IsE164 requires international phone-number syntax, without assignment checks.

func (StringField[T]) IsEmail

func (b StringField[T]) IsEmail() StringField[T]

IsEmail requires a bare ASCII mailbox with a dotted domain.

func (StringField[T]) IsHostname

func (b StringField[T]) IsHostname() StringField[T]

IsHostname requires ASCII DNS labels, optionally ending in a root dot.

func (StringField[T]) IsIP

func (b StringField[T]) IsIP() StringField[T]

IsIP requires an unzoned IP address literal.

func (StringField[T]) IsIPv4

func (b StringField[T]) IsIPv4() StringField[T]

IsIPv4 requires an IPv4 address literal.

func (StringField[T]) IsIPv6

func (b StringField[T]) IsIPv6() StringField[T]

IsIPv6 requires an unzoned IPv6 address literal.

func (StringField[T]) IsJSON

func (b StringField[T]) IsJSON() StringField[T]

IsJSON requires any valid JSON document, including scalar values.

func (StringField[T]) IsLowercase

func (b StringField[T]) IsLowercase() StringField[T]

IsLowercase requires valid UTF-8 with at least one cased letter and no uppercase or titlecase letters.

func (StringField[T]) IsMAC

func (b StringField[T]) IsMAC() StringField[T]

IsMAC requires a 48-bit or 64-bit link-layer address.

func (StringField[T]) IsULID

func (b StringField[T]) IsULID() StringField[T]

IsULID requires a case-insensitive 128-bit ULID.

func (StringField[T]) IsURL

func (b StringField[T]) IsURL() StringField[T]

IsURL requires an absolute HTTP or HTTPS URL with a host.

func (StringField[T]) IsUTF8

func (b StringField[T]) IsUTF8() StringField[T]

IsUTF8 requires valid UTF-8, including empty text.

func (StringField[T]) IsUUID

func (b StringField[T]) IsUUID() StringField[T]

IsUUID requires a canonical UUID, including nil and max UUIDs.

func (StringField[T]) IsUUIDv4

func (b StringField[T]) IsUUIDv4() StringField[T]

IsUUIDv4 requires a canonical version 4 UUID.

func (StringField[T]) IsUUIDv7

func (b StringField[T]) IsUUIDv7() StringField[T]

IsUUIDv7 requires a canonical version 7 UUID.

func (StringField[T]) IsUppercase

func (b StringField[T]) IsUppercase() StringField[T]

IsUppercase requires valid UTF-8 with at least one cased letter and no lowercase or titlecase letters.

func (StringField[T]) Label

func (b StringField[T]) Label(label string) StringField[T]

Label sets the human-readable field name without changing its output path.

func (StringField[T]) Len

func (b StringField[T]) Len(length int) StringField[T]

Len requires exactly length Unicode code points.

func (StringField[T]) Match

func (b StringField[T]) Match(pattern *regexp.Regexp) StringField[T]

Match requires a match against an already compiled, caller-owned expression.

func (StringField[T]) Max

func (b StringField[T]) Max(max int) StringField[T]

Max permits at most max Unicode code points.

func (StringField[T]) Message

func (b StringField[T]) Message(message string) StringField[T]

Message overrides the preceding rule message while preserving its code.

func (StringField[T]) Min

func (b StringField[T]) Min(min int) StringField[T]

Min requires at least min Unicode code points.

func (StringField[T]) NotBlank

func (b StringField[T]) NotBlank() StringField[T]

NotBlank rejects empty strings and strings containing only Unicode whitespace.

func (StringField[T]) NotContains

func (b StringField[T]) NotContains(text string) StringField[T]

NotContains rejects the configured substring without exposing it in failures.

func (StringField[T]) NotEqual

func (b StringField[T]) NotEqual(other T) StringField[T]

NotEqual rejects the other value without retaining it in failure details.

func (StringField[T]) NotIn

func (b StringField[T]) NotIn(values ...T) StringField[T]

NotIn rejects the listed values and owns a copy of their slice.

func (StringField[T]) Required

func (b StringField[T]) Required() StringField[T]

Required rejects an empty string before content rules run.

func (StringField[T]) RequiredIf

func (b StringField[T]) RequiredIf(condition bool) StringField[T]

RequiredIf applies an emptiness check only when condition is true.

func (StringField[T]) StartsWith

func (b StringField[T]) StartsWith(prefix string) StringField[T]

StartsWith requires a literal prefix.

func (StringField[T]) Using

func (b StringField[T]) Using(rule Rule[T]) StringField[T]

Using attaches a reusable validator for the exact value type.

type TimeField

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

TimeField is an immutable fluent chain for time instants.

func Time

func Time(path string, value time.Time) TimeField

Time starts a deferred chain using instant comparisons across time zones.

func (TimeField) After

func (b TimeField) After(other time.Time) TimeField

After requires an instant strictly later than other.

func (TimeField) Before

func (b TimeField) Before(other time.Time) TimeField

Before requires an instant strictly earlier than other.

func (TimeField) Check

func (b TimeField) Check(check func(context.Context, time.Time) error) TimeField

Check attaches a context-aware application check.

func (TimeField) Equal

func (b TimeField) Equal(other time.Time) TimeField

Equal requires the same instant without exposing the expected value in failures.

func (TimeField) Label

func (b TimeField) Label(label string) TimeField

Label sets the human-readable field name without changing its output path.

func (TimeField) Max

func (b TimeField) Max(max time.Time) TimeField

Max permits instants on or before max.

func (TimeField) Message

func (b TimeField) Message(message string) TimeField

Message overrides the preceding rule message while preserving its code.

func (TimeField) Min

func (b TimeField) Min(min time.Time) TimeField

Min permits instants on or after min.

func (TimeField) Required

func (b TimeField) Required() TimeField

Required rejects the zero time before content rules run.

func (TimeField) RequiredIf

func (b TimeField) RequiredIf(condition bool) TimeField

RequiredIf rejects the zero time when condition is true.

func (TimeField) Using

func (b TimeField) Using(rule Rule[time.Time]) TimeField

Using attaches a reusable validator for time values.

type Validator

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

Validator is an immutable evaluation policy; its zero value uses package defaults. Rule and formatter callbacks retain application ownership and concurrency requirements.

func New

func New() Validator

New creates a validator with first-violation-per-field collection and default messages.

func (Validator) CollectAll

func (v Validator) CollectAll() Validator

CollectAll collects all content failures per field; required failures still stop that field.

func (Validator) FormatMessages

func (v Validator) FormatMessages(format func(Issue) string) Validator

FormatMessages formats violations by path, code, and owned parameters, unless Message overrides it. The callback receives no submitted value and may provide application-localized messages.

func (Validator) StopOnFirstError

func (v Validator) StopOnFirstError() Validator

StopOnFirstError stops the entire evaluation after its first input violation.

func (Validator) Validate

func (v Validator) Validate(fields ...Field) error

Validate evaluates fields with a background context and the configured policy.

func (Validator) ValidateContext

func (v Validator) ValidateContext(ctx context.Context, fields ...Field) error

ValidateContext evaluates with request cancellation and the configured collection policy.

type ValueField

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

ValueField is an immutable fluent chain for value values.

func Value

func Value[T any](path string, value T) ValueField[T]

Value starts a deferred chain for a borrowed application value.

func (ValueField[T]) Check

func (b ValueField[T]) Check(check func(context.Context, T) error) ValueField[T]

Check attaches a context-aware application check.

func (ValueField[T]) Label

func (b ValueField[T]) Label(label string) ValueField[T]

Label sets the human-readable field name without changing its output path.

func (ValueField[T]) Message

func (b ValueField[T]) Message(message string) ValueField[T]

Message overrides the preceding rule message while preserving its code.

func (ValueField[T]) Using

func (b ValueField[T]) Using(rule Rule[T]) ValueField[T]

Using attaches a reusable validator for the exact value type.

type Violation

type Violation = violation.Violation

Violation is a coded, client-facing failure returned by a rule.

func Invalid

func Invalid(code, message string) *Violation

Invalid creates a violation with a stable code and a message safe for clients.

Directories

Path Synopsis
examples
advanced command
constraints command
context command
custom command
domain command
errors command
formats command
moreformats command
nested command
patch command
policies command
presence command
quickstart command
time command
internal
formats
Package formats owns the checks behind fluent string format methods.
Package formats owns the checks behind fluent string format methods.
violation
Package violation shares coded failures between validation and format rules.
Package violation shares coded failures between validation and format rules.

Jump to

Keyboard shortcuts

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