Documentation
¶
Overview ¶
Package validation provides a type-safe validation framework using Go generics.
This package offers compile-time type safety for validators, ensuring that validators can only be applied to compatible types. For example, a MinLength validator can only be used on strings, not integers.
Example usage:
func (input CreateUserInput) Validate() error {
return errors.Join(
validation.Validate(input.Email,
validation.Required[string](),
validation.IsEmail(),
),
validation.Validate(input.Age,
validation.Required[int](),
validation.Range(18, 120),
),
)
}
Example ¶
Example demonstrates basic validation usage
package main
import (
"errors"
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
type CreateUser struct {
Email string
Username string
Age int
}
input := CreateUser{
Email: "test@example.com",
Username: "john123",
Age: 25,
}
err := errors.Join(
validation.Validate(input.Email,
validation.Required[string](),
validation.Contains("@"),
),
validation.Validate(input.Username,
validation.Required[string](),
validation.Length(3, 20),
validation.MatchesPattern(`^[a-zA-Z0-9]+$`),
),
validation.Validate(input.Age,
validation.Required[int](),
validation.Range(18, 120),
),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (AnyMapValidation) ¶
Example_anyMapValidation demonstrates validating map[string]any (JSON-style data)
package main
import (
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
data := map[string]any{
"name": "John Doe",
"age": 30,
"active": true,
}
err := validation.ValidateAnyMap(
data,
true, // allow extra keys
validation.MapKey("name", true, validation.StringValidator(validation.Required[string]())),
validation.MapKey("age", true, validation.IntValidator(validation.Range(0, 120))),
validation.MapKey("active", false, validation.BoolValidator(validation.Custom(func(v bool) error {
return nil // Any bool value is fine
}))),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (ComposedValidators) ¶
Example_composedValidators demonstrates using And, Or, and Not
package main
import (
"errors"
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
// Complex password validator: min 8 chars, has uppercase, has number
passwordValidator := validation.And(
validation.MinLength(8),
validation.MatchesPattern(`[A-Z]`), // has uppercase
validation.MatchesPattern(`[0-9]`), // has number
)
// Email or phone validator
contactValidator := validation.Or(
validation.Contains("@"),
validation.MatchesPattern(`^\+\d{10,}$`),
)
password := "SecureP@ss123"
contact := "test@example.com"
err := errors.Join(
validation.Validate(password, passwordValidator),
validation.Validate(contact, contactValidator),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (ConditionalValidation) ¶
ExampleConditionalValidation demonstrates conditional validation
package main
import (
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
type Order struct {
RequiresShipping bool
ShippingAddress string
}
input := Order{
RequiresShipping: false,
ShippingAddress: "", // Empty, but that's okay since RequiresShipping is false
}
err := validation.Validate(input.ShippingAddress,
validation.When(
input.RequiresShipping,
validation.Required[string](),
),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (CustomValidator) ¶
ExampleCustomValidator demonstrates creating custom validators
package main
import (
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
// Define a custom validator
IsPositiveEven := func() validation.Validator[int] {
return func(v int) error {
if v <= 0 {
return fmt.Errorf("must be positive")
}
if v%2 != 0 {
return fmt.Errorf("must be even")
}
return nil
}
}
err := validation.Validate(4, IsPositiveEven())
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (DateValidation) ¶
Example_dateValidation demonstrates date and time validation
package main
import (
"errors"
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
// RFC3339 datetime
timestamp := "2024-12-31T23:59:59Z"
// ISO8601 date only
birthDate := "1990-05-15"
err := errors.Join(
validation.Validate(timestamp, validation.IsRFC3339DateTime()),
validation.Validate(birthDate, validation.IsISO8601Date()),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (MapValidation) ¶
Example_mapValidation demonstrates validating map[string]string
package main
import (
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
config := map[string]string{
"host": "localhost",
"port": "8080",
}
err := validation.ValidateStringMap(
config,
true, // allow extra keys
validation.MapKey("host", true, validation.Required[string]()),
validation.MapKey("port", true, validation.IsInt()),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (NestedValidation) ¶
Example_nestedValidation demonstrates validating nested structs
package main
import (
"errors"
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
type Address struct {
Street string
City string
}
type User struct {
Name string
Address Address
}
// Address implements Validatable interface
validateAddress := func(a Address) error {
return errors.Join(
validation.Validate(a.Street, validation.Required[string]()),
validation.Validate(a.City, validation.Required[string]()),
)
}
user := User{
Name: "John Doe",
Address: Address{
Street: "123 Main St",
City: "Springfield",
},
}
err := errors.Join(
validation.Validate(user.Name, validation.Required[string]()),
validateAddress(user.Address),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (OptionalFields) ¶
ExampleOptionalFields demonstrates validation of optional pointer fields
package main
import (
"errors"
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
type UpdateUser struct {
Email *string
Age *int
}
email := "test@example.com"
age := 25
input := UpdateUser{
Email: &email,
Age: &age,
}
err := errors.Join(
validation.Validate(input.Email,
validation.NilOr(validation.Contains("@")),
),
validation.Validate(input.Age,
validation.NilOr(validation.Range(0, 120)),
),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Example (SliceValidation) ¶
ExampleSliceValidation demonstrates validation of slices
package main
import (
"fmt"
"github.com/quantumcycle/protego/validation"
)
func main() {
emails := []string{"test1@example.com", "test2@example.com", "test3@example.com"}
err := validation.Validate(emails,
validation.NotEmpty[string](),
validation.MaxItems[string](10),
validation.Each(validation.Contains("@")),
)
if err != nil {
fmt.Println("Validation failed:", err)
} else {
fmt.Println("Validation passed")
}
}
Output: Validation passed
Index ¶
- func IsValidationError(err error) bool
- func NewValidationError(msg string) error
- func Validate[T any](value T, validators ...Validator[T]) error
- func ValidateAnyMap(m map[string]any, allowExtra bool, rules ...MapKeyRule[any]) error
- func ValidateNested[T any](value T) error
- func ValidateStringMap(m map[string]string, allowExtra bool, rules ...MapKeyRule[string]) error
- func WrapError(err error) error
- type Error
- type MapKeyRule
- type Validatable
- type Validator
- func And[T any](validators ...Validator[T]) Validator[T]
- func BoolValidator(validator Validator[bool]) Validator[any]
- func Contains(substring string) Validator[string]
- func Custom[T any](fn func(T) error) Validator[T]
- func Each[T any](elementValidator Validator[T]) Validator[[]T]
- func EndsWith(suffix string) Validator[string]
- func FloatValidator(validator Validator[float64]) Validator[any]
- func GreaterThan[T constraints.Ordered](threshold T) Validator[T]
- func In[T comparable](caseInsensitive bool, allowed ...T) Validator[T]
- func InSlice[T comparable](caseInsensitive bool, allowed []T) Validator[T]
- func IntValidator(validator Validator[int]) Validator[any]
- func IsDateAfter(afterDate string) Validator[string]
- func IsDateAfterFormat(afterDate, layout string) Validator[string]
- func IsDateBefore(beforeDate string) Validator[string]
- func IsDateBeforeFormat(beforeDate, layout string) Validator[string]
- func IsDateFormat(layout string) Validator[string]
- func IsFutureDate() Validator[string]
- func IsFutureDateFormat(layout string) Validator[string]
- func IsFutureTime() Validator[time.Time]
- func IsISO8601Date() Validator[string]
- func IsInt() Validator[string]
- func IsPastDate() Validator[string]
- func IsPastDateFormat(layout string) Validator[string]
- func IsPastTime() Validator[time.Time]
- func IsRFC3339DateTime() Validator[string]
- func IsTimeAfter(after time.Time) Validator[time.Time]
- func IsTimeBefore(before time.Time) Validator[time.Time]
- func Length(minimum, maximum int) Validator[string]
- func LessThan[T constraints.Ordered](threshold T) Validator[T]
- func MatchesPattern(pattern string) Validator[string]
- func Max[T constraints.Ordered](maximum T) Validator[T]
- func MaxItems[T any](maximum int) Validator[[]T]
- func MaxLength(maximum int) Validator[string]
- func Min[T constraints.Ordered](minimum T) Validator[T]
- func MinItems[T any](minimum int) Validator[[]T]
- func MinLength(minimum int) Validator[string]
- func MultipleOf[T constraints.Integer](divisor T) Validator[T]
- func Negative[T constraints.Ordered]() Validator[T]
- func Nested[T Validatable]() Validator[T]
- func NilOr[T any](validator Validator[T]) Validator[*T]
- func NilOrNotEmpty() Validator[*string]
- func NonNegative[T constraints.Ordered]() Validator[T]
- func Not[T any](validator Validator[T]) Validator[T]
- func NotEmpty[T any]() Validator[[]T]
- func NotIn[T comparable](caseInsensitive bool, forbidden ...T) Validator[T]
- func NotNil[T any]() Validator[*T]
- func OptionalWith[T any](validators ...Validator[T]) Validator[*T]
- func Or[T any](validators ...Validator[T]) Validator[T]
- func Positive[T constraints.Ordered]() Validator[T]
- func Range[T constraints.Ordered](minimum, maximum T) Validator[T]
- func Required[T comparable]() Validator[T]
- func RequiredIf[T comparable](condition bool) Validator[T]
- func StartsWith(prefix string) Validator[string]
- func StringValidator(validator Validator[string]) Validator[any]
- func UniqueItems[T comparable]() Validator[[]T]
- func Unless[T any](condition bool, validator Validator[T]) Validator[T]
- func When[T any](condition bool, validator Validator[T]) Validator[T]
- func WithMessage[T any](validator Validator[T], message string) Validator[T]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsValidationError ¶
IsValidationError checks if an error is a validation Error or wraps one. This allows users to detect if an error came from Protego validation.
Example:
if validation.IsValidationError(err) {
// Handle validation error
}
func NewValidationError ¶
NewValidationError creates a new validation Error with the given message. This should be used for creating new validation errors in validators.
Example:
return validation.NewValidationError("must be at least 3 characters")
func Validate ¶
Validate applies multiple validators to a value and returns the first error encountered. All validators are applied in order, and validation stops at the first failure.
Example:
err := validation.Validate(name,
validation.Required[string](),
validation.MinLength(3),
validation.MaxLength(50),
)
func ValidateAnyMap ¶
ValidateAnyMap validates a map[string]any (JSON-style map) with the specified rules. If allowExtra is false, any keys not defined in rules will cause an error.
Example:
err := validation.ValidateAnyMap(
jsonData,
true, // allow extra keys
validation.MapKey("name", true, validation.StringValidator(validation.Required[string]())),
validation.MapKey("age", false, validation.AnyValidator(func(v any) error {
age, ok := v.(float64)
if !ok { return fmt.Errorf("must be a number") }
return validation.Validate(int(age), validation.Range(0, 120))
})),
)
func ValidateNested ¶
ValidateNested checks if the value implements Validatable and calls its Validate() method. If the value doesn't implement Validatable, it returns nil (no validation performed).
Example:
type Address struct { ... }
func (a Address) Validate() error { ... }
type User struct {
Name string
Address Address
}
func (u User) Validate() error {
return errors.Join(
validation.Validate(u.Name, validation.Required[string]()),
validation.ValidateNested(u.Address), // Calls Address.Validate()
)
}
func ValidateStringMap ¶
ValidateStringMap validates a map[string]string with the specified rules. If allowExtra is false, any keys not defined in rules will cause an error.
Example:
err := validation.ValidateStringMap(
config,
true, // allow extra keys
validation.MapKey("host", true, validation.Required[string]()),
validation.MapKey("port", true, validation.IsInt()),
)
Types ¶
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error represents an error that occurred during validation. It wraps validation errors to make them identifiable as Protego errors.
type MapKeyRule ¶
type MapKeyRule[V any] struct { // contains filtered or unexported fields }
MapKeyRule represents a validation rule for a specific key in a map.
type Validatable ¶
type Validatable interface {
Validate() error
}
Validatable is an interface for types that have a Validate() method. This is useful for nested struct validation.
type Validator ¶
Validator is a generic validation function that validates a value of type T. It returns an error if validation fails, or nil if the value is valid.
func And ¶
And combines multiple validators - all must pass for validation to succeed. This is the default behavior of Validate, but And can be useful for composition.
Example:
passwordValidator := validation.And(
validation.MinLength(8),
validation.MatchesPattern(`[A-Z]`), // must have uppercase
validation.MatchesPattern(`[0-9]`), // must have number
)
validation.Validate(password, passwordValidator)
func BoolValidator ¶
BoolValidator converts a bool validator to work with any type by first asserting it's a boolean. This is useful for ValidateAnyMap when you know a value should be a bool.
Example:
validation.MapKey("active", true, validation.BoolValidator(validation.Custom(func(v bool) error {
if !v { return fmt.Errorf("must be active") }
return nil
})))
func Contains ¶
Contains validates that a string contains the specified substring.
Example:
validation.Validate(text, validation.Contains("important"))
func Custom ¶
Custom creates a custom validator from a function. This is useful for inline validators or wrapping complex validation logic.
Example:
validation.Validate(username,
validation.Custom(func(v string) error {
if containsProfanity(v) {
return fmt.Errorf("contains inappropriate content")
}
return nil
}),
)
func Each ¶
Each validates each element in a slice using the provided element validator. All errors are collected and returned as a joined error.
Example:
validation.Validate(emails, validation.Each(validation.IsEmail())) validation.Validate(ages, validation.Each(validation.Range(0, 120)))
func EndsWith ¶
EndsWith validates that a string ends with the specified suffix.
Example:
validation.Validate(filename, validation.EndsWith(".json"))
func FloatValidator ¶
FloatValidator converts a float64 validator to work with any type by first asserting it's a number. This is useful for ValidateAnyMap when you know a value should be a float.
Example:
validation.MapKey("price", true, validation.FloatValidator(validation.Min(0.0)))
func GreaterThan ¶
func GreaterThan[T constraints.Ordered](threshold T) Validator[T]
GreaterThan validates that a value is strictly greater than the specified value.
Example:
validation.Validate(count, validation.GreaterThan(0))
func In ¶
func In[T comparable](caseInsensitive bool, allowed ...T) Validator[T]
In validates that a value is in the allowed list. If caseInsensitive is true, string values are compared case-insensitively.
Example:
validation.Validate(status, validation.In(false, "ACTIVE", "INACTIVE", "PENDING")) validation.Validate(mode, validation.In(true, "single", "multiple")) // case-insensitive
func InSlice ¶
func InSlice[T comparable](caseInsensitive bool, allowed []T) Validator[T]
InSlice validates that a value is in the allowed slice. This is similar to In but takes a slice instead of variadic arguments.
Example:
allowedCurrencies := []string{"USD", "EUR", "GBP"}
validation.Validate(currency, validation.InSlice(true, allowedCurrencies))
func IntValidator ¶
IntValidator converts an int validator to work with any type by first asserting it's a number. This is useful for ValidateAnyMap when you know a value should be an int.
Example:
validation.MapKey("age", true, validation.IntValidator(validation.Range(0, 120)))
func IsDateAfter ¶
IsDateAfter validates that a string represents a date after the specified date. Both dates are parsed as RFC3339 format.
Example:
validation.Validate(endDate, validation.IsDateAfter("2024-01-01T00:00:00Z"))
func IsDateAfterFormat ¶
IsDateAfterFormat validates that a string represents a date after the specified date. Both dates are parsed using the specified layout.
Example:
validation.Validate(endDate, validation.IsDateAfterFormat("2024-01-01", "2006-01-02"))
func IsDateBefore ¶
IsDateBefore validates that a string represents a date before the specified date. Both dates are parsed as RFC3339 format.
Example:
validation.Validate(startDate, validation.IsDateBefore("2024-12-31T23:59:59Z"))
func IsDateBeforeFormat ¶
IsDateBeforeFormat validates that a string represents a date before the specified date. Both dates are parsed using the specified layout.
Example:
validation.Validate(startDate, validation.IsDateBeforeFormat("2024-12-31", "2006-01-02"))
func IsDateFormat ¶
IsDateFormat validates that a string matches the specified date format. The layout uses Go's time format layout (reference time: Mon Jan 2 15:04:05 MST 2006).
Example:
validation.Validate(date, validation.IsDateFormat("2006-01-02 15:04:05"))
func IsFutureDate ¶
IsFutureDate validates that a string represents a date in the future. The date is parsed as RFC3339 format.
Example:
validation.Validate(expiryDate, validation.IsFutureDate())
func IsFutureDateFormat ¶
IsFutureDateFormat validates that a string represents a date in the future. The date is parsed using the specified layout.
Example:
validation.Validate(expiryDate, validation.IsFutureDateFormat("2006-01-02"))
func IsFutureTime ¶
IsFutureTime validates that a time.Time is in the future.
Example:
validation.Validate(expiryTime, validation.IsFutureTime())
func IsISO8601Date ¶
IsISO8601Date validates that a string is a valid ISO8601 date in YYYY-MM-DD format.
Example:
validation.Validate(birthDate, validation.IsISO8601Date())
func IsInt ¶
IsInt validates that a string represents a valid integer.
Example:
validation.Validate(idString, validation.IsInt())
func IsPastDate ¶
IsPastDate validates that a string represents a date in the past. The date is parsed as RFC3339 format.
Example:
validation.Validate(birthDate, validation.IsPastDate())
func IsPastDateFormat ¶
IsPastDateFormat validates that a string represents a date in the past. The date is parsed using the specified layout.
Example:
validation.Validate(birthDate, validation.IsPastDateFormat("2006-01-02"))
func IsPastTime ¶
IsPastTime validates that a time.Time is in the past.
Example:
validation.Validate(birthTime, validation.IsPastTime())
func IsRFC3339DateTime ¶
IsRFC3339DateTime validates that a string is a valid RFC3339 date-time. RFC3339 is the standard format used by JSON and most APIs (e.g., "2006-01-02T15:04:05Z07:00").
Example:
validation.Validate(timestamp, validation.IsRFC3339DateTime())
func IsTimeAfter ¶
IsTimeAfter validates that a time.Time is after the specified time.
Example:
validation.Validate(endTime, validation.IsTimeAfter(startTime))
func IsTimeBefore ¶
IsTimeBefore validates that a time.Time is before the specified time.
Example:
validation.Validate(startTime, validation.IsTimeBefore(endTime))
func Length ¶
Length validates that a string length is between minimum and maximum (inclusive).
Example:
validation.Validate(username, validation.Length(3, 20))
func LessThan ¶
func LessThan[T constraints.Ordered](threshold T) Validator[T]
LessThan validates that a value is strictly less than the specified value.
Example:
validation.Validate(percentage, validation.LessThan(100.0))
func MatchesPattern ¶
MatchesPattern validates that a string matches the given regular expression pattern.
Example:
validation.Validate(code, validation.MatchesPattern(`^[A-Z]{3}-\d{4}$`))
func Max ¶
func Max[T constraints.Ordered](maximum T) Validator[T]
Max validates that a value is less than or equal to the specified maximum.
Example:
validation.Validate(age, validation.Max(120)) validation.Validate(discount, validation.Max(1.0))
func MaxItems ¶
MaxItems validates that a slice has at most the specified maximum number of items.
Example:
validation.Validate(tags, validation.MaxItems[string](10))
func MaxLength ¶
MaxLength validates that a string has at most the specified maximum length.
Example:
validation.Validate(name, validation.MaxLength(50))
func Min ¶
func Min[T constraints.Ordered](minimum T) Validator[T]
Min validates that a value is greater than or equal to the specified minimum.
Example:
validation.Validate(age, validation.Min(18)) validation.Validate(price, validation.Min(0.0))
func MinItems ¶
MinItems validates that a slice has at least the specified minimum number of items.
Example:
validation.Validate(tags, validation.MinItems[string](1))
func MinLength ¶
MinLength validates that a string has at least the specified minimum length.
Example:
validation.Validate(name, validation.MinLength(3))
func MultipleOf ¶
func MultipleOf[T constraints.Integer](divisor T) Validator[T]
MultipleOf validates that a numeric value is a multiple of the specified divisor.
Example:
validation.Validate(quantity, validation.MultipleOf(5))
func Negative ¶
func Negative[T constraints.Ordered]() Validator[T]
Negative validates that a numeric value is less than zero.
Example:
validation.Validate(debit, validation.Negative[float64]())
func Nested ¶
func Nested[T Validatable]() Validator[T]
Nested returns a validator that calls the Validate() method on nested structs. This is a wrapper around ValidateNested for use with the Validate function.
Example:
validation.Validate(user.Address, validation.Nested[Address]())
func NilOr ¶
NilOr wraps a validator to make it work with optional (pointer) fields. If the pointer is nil, validation passes. If not nil, the wrapped validator is applied.
Example:
type UpdateUserInput struct {
Email *string
Age *int
Priority *int
}
func (input UpdateUserInput) Validate() error {
return errors.Join(
validation.Validate(input.Email,
validation.NilOr(validation.IsEmail()),
),
validation.Validate(input.Age,
validation.NilOr(validation.Range(0, 120)),
),
validation.Validate(input.Priority,
validation.NilOr(validation.In(false, 1, 2, 3)),
),
)
}
func NilOrNotEmpty ¶
NilOrNotEmpty validates that a pointer to string is either nil or not empty. This is useful for optional fields that, if provided, must not be empty.
Example:
type UpdateUserInput struct {
Name *string
}
validation.Validate(input.Name, validation.NilOrNotEmpty())
func NonNegative ¶
func NonNegative[T constraints.Ordered]() Validator[T]
NonNegative validates that a numeric value is greater than or equal to zero.
Example:
validation.Validate(count, validation.NonNegative[int]())
func Not ¶
Not inverts a validator - it passes if the validator fails, and vice versa.
Example:
validation.Validate(username,
validation.Not(validation.In(false, "admin", "root")), // must NOT be admin or root
)
func NotEmpty ¶
NotEmpty validates that a slice is not empty.
Example:
validation.Validate(tags, validation.NotEmpty[string]())
func NotIn ¶
func NotIn[T comparable](caseInsensitive bool, forbidden ...T) Validator[T]
NotIn validates that a value is NOT in the forbidden list.
Example:
validation.Validate(username, validation.NotIn(false, "admin", "root", "system"))
func NotNil ¶
NotNil validates that a pointer is not nil.
Example:
validation.Validate(input.RequiredField, validation.NotNil[string]())
func OptionalWith ¶
OptionalWith validates an optional field with multiple validators if it's not nil. This is a convenience function that combines NilOr with multiple validators.
Example:
validation.Validate(input.Email,
validation.OptionalWith(
validation.IsEmail(),
validation.MinLength(5),
),
)
func Or ¶
Or combines multiple validators - at least one must pass for validation to succeed. If all validators fail, a combined error is returned.
Example:
// Accept either email or phone number
validation.Validate(contact,
validation.Or(
validation.IsEmail(),
validation.MatchesPattern(`^\+\d{10,}$`), // phone pattern
),
)
func Positive ¶
func Positive[T constraints.Ordered]() Validator[T]
Positive validates that a numeric value is greater than zero.
Example:
validation.Validate(amount, validation.Positive[int]()) validation.Validate(price, validation.Positive[float64]())
func Range ¶
func Range[T constraints.Ordered](minimum, maximum T) Validator[T]
Range validates that a value is between minimum and maximum (inclusive).
Example:
validation.Validate(age, validation.Range(18, 120)) validation.Validate(rating, validation.Range(1, 5))
func Required ¶
func Required[T comparable]() Validator[T]
Required validates that a value is not the zero value for its type. For strings, this means not empty. For numbers, this means not zero. For pointers, this means not nil.
Example:
validation.Validate(name, validation.Required[string]()) validation.Validate(age, validation.Required[int]())
func RequiredIf ¶
func RequiredIf[T comparable](condition bool) Validator[T]
RequiredIf validates that a value is not the zero value if the condition is true. If the condition is false, validation passes regardless of the value.
Example:
validation.Validate(input.ShippingAddress,
validation.RequiredIf[string](input.RequiresShipping),
)
func StartsWith ¶
StartsWith validates that a string starts with the specified prefix.
Example:
validation.Validate(packageName, validation.StartsWith("com."))
func StringValidator ¶
StringValidator converts a string validator to work with any type by first asserting it's a string. This is useful for ValidateAnyMap when you know a value should be a string.
Example:
validation.MapKey("email", true, validation.StringValidator(validation.IsEmail()))
func UniqueItems ¶
func UniqueItems[T comparable]() Validator[[]T]
UniqueItems validates that all items in a slice are unique.
Example:
validation.Validate(ids, validation.UniqueItems[string]())
func Unless ¶
Unless applies a validator only if the condition is false. This is the opposite of When.
Example:
validation.Validate(input.Reason,
validation.Unless(
input.IsApproved,
validation.Required[string](), // reason required if not approved
),
)
func When ¶
When applies a validator only if the condition is true. This is useful for conditional validation.
Example:
validation.Validate(input.ShippingAddress,
validation.When(
input.RequiresShipping,
validation.Required[string](),
),
)
func WithMessage ¶
WithMessage wraps a validator and replaces its error message with a custom message. This is useful when you want to provide more specific or user-friendly error messages.
Example:
validation.Validate(input.Count,
validation.WithMessage(
validation.Required[int](),
"count cannot be zero",
),
)