Goov
goov is a powerful and lightweight schema validator for Go, designed to handle validation of complex data structures with ease. It supports custom rules, nested validation, and various data types. Ideal for validating JSON, structs, and other input formats.
Install / Use
/learn @sgh370/GoovREADME
GOOV - Go Object Validator
GOOV is a powerful, flexible, and easy-to-use validation library for Go that provides struct-level validation through tags. It offers a wide range of built-in validation rules and supports custom validation logic.
Author
Saeed Ghanbari - GitHub
Features
- Tag-based validation
- Extensive set of built-in validators
- Conditional validation
- Cross-field validation
- Slice and map validation
- Custom validation rules
- Multiple error handling
- DNS validation for emails
- Nested struct validation
Installation
go get github.com/sgh370/goov
Quick Start
package main
import (
"fmt"
"github.com/sgh370/goov/validator"
"github.com/sgh370/goov/validator/rules"
)
type User struct {
Username string `validate:"required,length:3:20"`
Email string `validate:"required,email"`
Age int `validate:"required,min=18"`
Interests []string `validate:"required,min=1,dive,required"`
}
func main() {
// Create a new validator instance
v := validator.New()
// Add validation rules
v.AddRule("required", rules.Required{})
v.AddRule("length:3:20", &rules.Length{Min: 3, Max: 20})
v.AddRule("min=18", &rules.Min{Value: 18})
v.AddRule("email", &rules.EmailDNS{})
// Create a user to validate
user := User{
Username: "johndoe",
Email: "john@example.com",
Age: 25,
Interests: []string{"coding", "reading"},
}
// Validate the user
if err := v.Validate(user); err != nil {
fmt.Printf("Validation failed: %v\n", err)
return
}
fmt.Println("User is valid!")
}
Available Validation Rules
Common Rules
required- Ensures a value is not emptylength:min:max- Validates string/slice/map lengthmin=value- Validates minimum numeric valuemax=value- Validates maximum numeric valueoneof=value1 value2- Ensures value is one of the specified optionsemail- Validates email format with DNS checkurl- Validates URL formatip- Validates IP address formatuuid- Validates UUID formatjson- Validates JSON string format
Numeric Rules
positive- Ensures number is positiverange=min:max- Validates number within range
Collection Rules
unique- Ensures slice elements are uniquecontains=value- Checks if slice/array contains valueeach=rule- Applies rule to each elementdive- Validates nested slice elements
Conditional Rules
required_if=field value- Conditional required validationif=field then=rule- Conditional rule applicationunless=field then=rule- Inverse conditional validation
Advanced Rules
password- Validates password complexitycreditcard- Validates credit card numbersphone- Validates phone numberssemver- Validates semantic version stringsdomain- Validates domain namesport- Validates port numbers
Pre-registered Validation Tags
GOOV comes with several pre-registered validation rules that are ready to use without calling AddRule. These are common validation rules that are automatically registered when you create a new validator instance using validator.New().
Basic Pre-registered Rules
v := validator.New() // These rules are automatically registered
type User struct {
// All these tags work without explicit AddRule calls
ID int `validate:"required"`
Email string `validate:"email"`
URL string `validate:"url"`
IP string `validate:"ip"`
UUID string `validate:"uuid"`
JSON string `validate:"json"`
Phone string `validate:"phone"`
}
Pre-registered Rules List
-
Data Presence
required- Field must not be empty
-
String Formats
email- Validates email formaturl- Validates URL formatip- Validates IPv4 or IPv6 addressuuid- Validates UUID formatjson- Validates JSON string formatphone- Validates phone number format
-
Numeric Validations
positive- Number must be positivenegative- Number must be negativemin- Minimum value checkmax- Maximum value check
-
Collection Validations
unique- All elements must be uniquemin- Minimum number of elementsmax- Maximum number of elementsdive- Validates elements of a slice/array
Using Pre-registered Rules with Parameters
Some pre-registered rules accept parameters. Here's how to use them:
type Product struct {
// Numeric parameters
Age int `validate:"min=18"`
Score float64 `validate:"range=0:100"`
// String length
Name string `validate:"length=10"` // Exact length
Description string `validate:"length:5:100"` // Min:Max length
// Collection size
Tags []string `validate:"min=1,max=5"` // Between 1 and 5 elements
}
Combining Pre-registered Rules
You can combine multiple pre-registered rules in a single tag:
type User struct {
Email string `validate:"required,email"` // Must be present and valid email
Tags []string `validate:"required,min=1,unique"` // Required, non-empty, unique elements
Age int `validate:"required,min=0,max=150"` // Required, between 0 and 150
}
Important Notes
- Pre-registered rules are designed for common validation scenarios
- They are optimized for performance and memory usage
- You can override pre-registered rules by calling
AddRulewith the same name - Custom validation rules still need to be registered using
AddRule
Understanding AddRule and Tags
The Relationship Between AddRule and Tags
The validation system in GOOV works through two complementary components:
- AddRule: Registers validation rules with the validator instance
- Tags: Applies those registered rules to struct fields
Before a tag can be used in a struct, its corresponding rule must be registered using AddRule. Here's how it works:
// 1. First, register the rule
v.AddRule("length:3:20", &rules.Length{Min: 3, Max: 20})
// 2. Then use it in struct tags
type User struct {
Username string `validate:"length:3:20"`
}
When to Use AddRule
You need to use AddRule in these scenarios:
- When initializing your validator instance
- When defining parameterized rules (e.g.,
length:3:20,min=18) - When adding custom validation rules
- When setting up conditional validations
Example of registering different types of rules:
v := validator.New()
// Simple rules
v.AddRule("required", rules.Required{})
// Parameterized rules
v.AddRule("length:3:20", &rules.Length{Min: 3, Max: 20})
v.AddRule("min=18", &rules.Min{Value: 18})
// Conditional rules
v.AddRule("required_if", &rules.If{
Field: "ContactMethod",
Then: rules.Required{},
})
When to Use Tags
Tags are used in your struct definitions to:
- Apply registered validation rules to specific fields
- Combine multiple validation rules
- Define the validation flow for your data model
Example of using tags:
type User struct {
// Single rule
IsActive bool `validate:"required"`
// Multiple rules
Username string `validate:"required,length:3:20"`
// Conditional validation
Phone string `validate:"required_if=ContactType phone"`
// Nested validation
Addresses []Address `validate:"required,dive"`
}
Remember: Any validation rule used in a tag must first be registered using AddRule. If you use a tag that hasn't been registered, the validator will return an error.
Custom Validation Rules
You can create custom validation rules by implementing the Rule interface:
type MyRule struct{}
func (r MyRule) Validate(value interface{}) error {
// Your validation logic here
return nil
}
// Add your custom rule
v.AddRule("myrule", MyRule{})
Cross-Field Validation
GOOV supports validation based on other field values:
type Form struct {
PaymentType string `validate:"required,oneof=card bank"`
CardNumber string `validate:"required_if=PaymentType card"`
BankAccount string `validate:"required_if=PaymentType bank"`
}
Error Handling
GOOV provides detailed error messages for validation failures. You can use ValidateAll to get all validation errors at once:
errors := v.ValidateAll(user)
for _, err := range errors {
fmt.Printf("Validation error: %v\n", err)
}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
