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

xvalidator

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 6, 2026 License: MIT Imports: 13 Imported by: 0

README

go-xvalidator

A powerful extension package for go-playground/validator that provides enhanced validation capabilities including decimal validation, phone number validation (E.164 format), URL validation, password strength validation, and localized error messages for Go applications.

Go Version License

Features

  • 🔢 Decimal Validation: Precise decimal comparison operators (greater than, less than, equal, etc.)
  • 📱 Phone Validation: International phone number validation with country-specific rules (E.164 format)
  • 🔗 URL Validation: Standard and HTTPS-only URL validation
  • 🔒 Password Strength: Comprehensive password strength validation
  • 🌍 Localization: Built-in English translations for validation errors
  • ✨ Easy Integration: Drop-in replacement for go-playground/validator

Table of Contents

Installation

go get github.com/hotfixfirst/go-xvalidator

Quick Start

package main

import (
    "fmt"
    "github.com/hotfixfirst/go-xvalidator"
)

func main() {
    // Create validator instance
    v, err := xvalidator.NewValidator()
    if err != nil {
        panic(err)
    }

    // Define your struct with validation tags
    type User struct {
        Name     string `json:"name" validate:"required,min=3"`
        Email    string `json:"email" validate:"required,email"`
        Phone    string `json:"phone" validate:"mobile_e164=US"`
        Balance  string `json:"balance" validate:"dgte=0"`
        Password string `json:"password" validate:"password_strength"`
    }

    // Validate
    user := User{
        Name:     "John Doe",
        Email:    "john.doe@example.com",
        Phone:    "+447912345678",
        Balance:  "1000.50",
        Password: "SecureP@ss123",
    }

    if err := v.Validate(user); err != nil {
        fmt.Printf("Validation failed: %v\n", err)
        return
    }

    fmt.Println("Validation passed!")
}

Available Validators

Decimal Validators

Validate decimal values with precise comparison:

type Product struct {
    Price    string `validate:"required,dgte=0,dlte=999999.99"`
    Discount string `validate:"dgte=0,dlte=100"`
    Quantity string `validate:"dgt=0"`
}

Tags:

  • decimal - Validates decimal format (precision and scale)
  • dgt=value - Decimal greater than
  • dgte=value - Decimal greater than or equal
  • dlt=value - Decimal less than
  • dlte=value - Decimal less than or equal
  • deq=value - Decimal equal to
  • dneq=value - Decimal not equal to
Conditional Decimal Validators

Validate decimals conditionally based on other field values:

type Payment struct {
    Method string `validate:"required,oneof=cash credit_card"`
    Amount string `validate:"required,decimal_if=Method cash dgte 0 decimal 10:0"`
    // Amount must be integer (0 decimals) if Method is "cash"
}

Tag:

  • decimal_if=FieldName FieldValue Operator CompareValue DecimalFormat
    • Only validates if FieldName equals FieldValue
    • Supports: dgt, dgte, dlt, dlte, deq, dneq
    • DecimalFormat: precision:scale (e.g., 10:2)
Phone Number Validators

Validate international phone numbers in E.164 format:

type Contact struct {
    PhoneGeneral string `validate:"mobile_e164"`        // Any country
    PhoneTH      string `validate:"mobile_e164=TH"`     // Thai mobile
    PhoneUS      string `validate:"mobile_e164=US"`     // US mobile
    PhoneGB      string `validate:"mobile_e164=GB"`     // UK mobile
}

Supported Countries:

  • TH - Thailand
  • US - United States
  • GB - United Kingdom
  • FR - France
  • And many more...
URL Validators

Validate URL formats:

type Website struct {
    Homepage string `validate:"url"`              // Any valid URL
    SecureAPI string `validate:"https_url"`       // HTTPS only
}
Password Strength Validator

Validate password complexity:

type Account struct {
    Password string `validate:"password_strength"`
}

// Or use standalone validation
err := xvalidator.ValidatePasswordStrength("MyP@ssw0rd")

Requirements:

  • Minimum 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character: !@#$%^&*()_+-=[]{}|;:,.<>?

Examples

See the _examples/ directory for 131 comprehensive examples across 10 categories.

📚 Example Categories
Getting Started
  • basic/ - Basic validation (10 examples)
    • Required fields, email, min/max validation
Feature-Specific
  • decimal/ - Decimal validation (22 examples)

    • Standard comparisons (dgt, dgte, dlt, dlte, deq, dneq)
    • Conditional validation (decimal_if)
    • Precision and scale validation
  • phone/ - E.164 phone validation (12 examples)

    • International formats (TH, US, UK, FR, DE, JP, etc.)
  • url/ - URL validation (13 examples)

    • HTTP/HTTPS validation with paths and parameters
  • password/ - Password strength (14 examples)

    • Complexity requirements and edge cases
Advanced Usage
  • nested-struct/ - Nested structures (10 examples)

    • Complex object validation with dive
  • custom-messages/ - Error translation (11 examples)

    • Localized messages and custom formats
  • advanced/ - Custom validators (5 examples)

    • Thai ID Card, Business Hours, Custom validators
  • real-world/ - Real scenarios (27 examples)

    • User registration, Payment processing, E-commerce orders
  • best-practices/ - Recommended patterns (7 examples)

    • String validation + decimal.Decimal workflow
🚀 Running Examples
# Run any example
cd _examples/basic
go run main.go

# Decimal has 2 files (run separately)
cd _examples/decimal
go run main.go
go run conditional.go

# Real-world has 3 files (run individually)
cd _examples/real-world
go run user-registration.go
go run payment.go
go run ecommerce.go

For complete documentation, see _examples/README.md

Best Practices

Decimal Handling for Monetary Values

✅ Recommended Pattern:

import "github.com/shopspring/decimal"

// 1. Use string in API/struct layer
type PriceRequest struct {
    Amount string `json:"amount" validate:"required,decimal=10:2,dgt=0"`
}

// 2. Validate using xvalidator
if err := validator.StructTranslated(req); err != nil {
    return err
}

// 3. Convert to decimal.Decimal for calculations
amount, _ := decimal.NewFromString(req.Amount)
tax := amount.Mul(decimal.NewFromFloat(0.07))
total := amount.Add(tax)

// 4. Format back to string for output
return total.StringFixed(2)

Why this pattern?

  • ✅ Prevents floating-point precision errors
  • ✅ Validates before processing
  • ✅ Maintains accuracy in calculations
  • ✅ Consistent between validation and business logic

❌ Avoid:

// Don't use float64 for money
type BadRequest struct {
    Amount float64 `json:"amount"` // ❌ Precision errors!
}

// Don't use decimal.Decimal directly in API structs
type BadRequest struct {
    Amount decimal.Decimal `json:"amount"` // ❌ JSON marshaling issues!
}

See _examples/best-practices/decimal-workflow.go for complete working examples.

Custom Validators

Create reusable custom validators:

func validateBusinessHours(fl validator.FieldLevel) bool {
    timeStr := fl.Field().String()
    t, err := time.Parse("15:04", timeStr)
    if err != nil {
        return false
    }
    
    start, _ := time.Parse("15:04", "09:00")
    end, _ := time.Parse("15:04", "17:00")
    
    return t.After(start) && t.Before(end)
}

// Register
v.GetValidator().RegisterValidation("business_hours", validateBusinessHours)

See _examples/advanced/main.go for more custom validator examples.

Testing

Run the test suite:

go test -v ./...

Run tests with coverage:

go test -v -cover ./...

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Built on top of the excellent go-playground/validator library.

Support

For questions and issues, please open an issue on GitHub.

Documentation

Index

Constants

View Source
const (
	// DefaultPrecision defines the default precision for decimal validation (total digits).
	DefaultPrecision = 38

	// DefaultScale defines the default scale for decimal validation (decimal places).
	DefaultScale = 18
)

Decimal validation default values

Variables

View Source
var (
	// E164Regex returns a compiled regex for validating E.164 phone numbers.
	E164Regex = lazyRegexCompile(e164RegexString)
)

Pre-compiled regex functions

Functions

func RegisterDecimalValidators

func RegisterDecimalValidators(v *validator.Validate)

RegisterDecimalValidators registers all decimal validation rules for shopspring/decimal.Decimal type. This function adds comprehensive decimal comparison validators that work with decimal.Decimal values.

func RegisterPasswordValidators

func RegisterPasswordValidators(v *validator.Validate)

RegisterPasswordValidators registers password validation rules. This function adds validators for password strength and complexity requirements.

func RegisterPhoneValidators

func RegisterPhoneValidators(v *validator.Validate)

RegisterPhoneValidators registers phone number validation rules using libphonenumber. This function adds validators for international phone number format and type validation.

func RegisterURLValidators

func RegisterURLValidators(v *validator.Validate)

RegisterURLValidators registers URL-specific validation rules. This function adds validators for URL format and protocol validation.

func ValidatePasswordStrength

func ValidatePasswordStrength(password string) error

ValidatePasswordStrength provides a public interface to validate password strength. Returns an error if the password doesn't meet the requirements.

Types

type Validator

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

Validator wraps go-playground/validator with enhanced decimal support and Universal Translator.

func NewValidator

func NewValidator() (*Validator, error)

NewValidator creates a new validator instance with all custom rules and English translator registered.

func (*Validator) GetTranslator

func (v *Validator) GetTranslator() ut.Translator

GetTranslator returns the Universal Translator instance.

func (*Validator) GetValidator

func (v *Validator) GetValidator() *validator.Validate

GetValidator returns the underlying validator.Validate instance.

func (*Validator) Struct

func (v *Validator) Struct(i any) error

Struct validates a struct and returns raw validation errors without translation. This method is an alias for Validate for consistency with other validator methods.

func (*Validator) StructTranslated

func (v *Validator) StructTranslated(s any) error

StructTranslated validates a struct based on tags and returns user-friendly translated error messages.

func (*Validator) Validate

func (v *Validator) Validate(i any) error

Validate validates a struct and returns raw validation errors without translation. For user-friendly error messages, use StructTranslated instead.

func (*Validator) Var

func (v *Validator) Var(field any, tag string) error

Var validates a single variable using the provided validation tag and returns raw errors. For user-friendly error messages, use VarTranslated instead.

func (*Validator) VarTranslated

func (v *Validator) VarTranslated(field any, tag string) error

VarTranslated validates a single variable using the provided validation tag and returns user-friendly translated error messages.

Directories

Path Synopsis
_examples
advanced command
basic command
best-practices command
custom-messages command
decimal command
nested-struct command
password command
phone command
real-world command
url command

Jump to

Keyboard shortcuts

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