README
¶
GoFlexValidation
A flexible and extensible validation library for Go applications. GoFlexValidation offers a simple yet powerful way to validate data structures with a variety of built-in validation rules and support for custom validation functions. My main goal with this package is to be able to apply validations like the C# FluentValidation library does, but in a simple and easy-to-use way.
Features
- Type-safe validation: Built with Go's reflection system for type-safe validation
- Extensible rule system: Easy to add custom validation rules
- Comprehensive error handling: Detailed error messages with field and rule information
- Multiple validation types: Support for equality, comparison, emptiness, pattern matching, and length validation
- Custom validators: Support for custom validation functions
- Clean API: Simple and intuitive API design
Installation
go get gitlab.com/jsalio/goflexvalidation
Quick Start
Validación de structs (recomendado)
package main
import (
"fmt"
"gitlab.com/jsalio/goflexvalidation/engine"
)
type User struct {
Username string
Age int
Email string
}
func main() {
// Crear un validador y agregar reglas
validator := engine.NewValidator()
validator.AddRule("Username", engine.ShouldNotEmpty, nil, "Username is required")
validator.AddRule("Age", engine.ShouldGreaterThan, 18, "Age must be greater than 18")
validator.AddRule("Email", engine.ShouldMatch, `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$`, "Invalid email format")
// Datos de prueba
user := User{
Username: "john_doe",
Age: 25,
Email: "john@example.com",
}
// Validar struct completo
result := validator.Validate(user)
if len(result.Errors) == 0 {
fmt.Println("✅ User passed all validations")
} else {
for _, err := range result.Errors {
fmt.Printf("❌ %s: %s\n", err.Field, err.Message)
}
}
}
Validación de mapas (map[string]interface{})
package main
import (
"fmt"
"gitlab.com/jsalio/goflexvalidation/engine"
)
func main() {
// Crear reglas de validación
validator := engine.NewValidator()
validator.AddRule(engine.ValidationRule{
FieldName: "username",
Rule: engine.ShouldNotEmpty,
Expected: "",
Message: stringPtr("Username is required"),
})
validator.AddRule(engine.ValidationRule{
FieldName: "age",
Rule: engine.ShouldGreaterThan,
Expected: 18,
Message: stringPtr("Age must be greater than 18"),
})
validator.AddRule(engine.ValidationRule{
FieldName: "email",
Rule: engine.ShouldMatch,
Expected: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$`,
Message: stringPtr("Invalid email format"),
})
}
// Datos de prueba
data := map[string]interface{}{
"username": "john_doe",
"age": 25,
"email": "john@example.com",
}
// Validar manualmente cada campo
result := validator.Validate(user)
if len(result.Errors) == 0 {
fmt.Println("✅ User passed all validations")
} else {
for _, err := range result.Errors {
fmt.Printf("❌ %s: %s\n", err.Field, err.Message)
}
}
}
func stringPtr(s string) *string {
return &s
}
Available Validation Rules
Equality Rules
ShouldEqual: Validates that a field equals a specific valueShouldNotEqual: Validates that a field does not equal a specific value
Comparison Rules
ShouldGreaterThan: Validates that a field is greater than a specific valueShouldGreaterOrEqualThan: Validates that a field is greater than or equal to a specific valueShouldLessThan: Validates that a field is less than a specific valueShouldLessOrEqualThan: Validates that a field is less than or equal to a specific value
Emptiness Rules
ShouldEmpty: Validates that a field is emptyShouldNotEmpty: Validates that a field is not empty
Pattern Matching Rules
ShouldMatch: Validates that a field matches a specific regex patternShouldNotMatch: Validates that a field does not match a specific regex pattern
Length Rules
ShouldLength: Validates that a field has a specific lengthShouldMinLength: Validates that a field has a minimum length
Custom Rules
Must: Validates using a custom validation function
Usage Examples
Basic Validation
rule := engine.ValidationRule{
FieldName: "name",
Rule: engine.ShouldNotEmpty,
Expected: "",
Message: stringPtr("Name is required"),
}
err := rule.Validate("")
if err != nil {
fmt.Println(err.Message) // Output: Name is required
}
Numeric Validation
rule := engine.ValidationRule{
FieldName: "score",
Rule: engine.ShouldGreaterThan,
Expected: 0,
Message: stringPtr("Score must be positive"),
}
err := rule.Validate(10)
if err != nil {
fmt.Println(err.Message)
}
Pattern Matching
rule := engine.ValidationRule{
FieldName: "phone",
Rule: engine.ShouldMatch,
Expected: `^\d{3}-\d{3}-\d{4}$`,
Message: stringPtr("Phone number must be in format XXX-XXX-XXXX"),
}
err := rule.Validate("123-456-7890")
if err != nil {
fmt.Println(err.Message)
}
Length Validation
rule := engine.ValidationRule{
FieldName: "password",
Rule: engine.ShouldMinLength,
Expected: 8,
Message: stringPtr("Password must be at least 8 characters long"),
}
err := rule.Validate("short")
if err != nil {
fmt.Println(err.Message) // Output: Password must be at least 8 characters long
}
Custom Validation
// Define custom validation function
func validateEvenNumber(value interface{}) (bool, string) {
if v, ok := value.(int); ok {
if v%2 == 0 {
return true, ""
}
return false, "Number must be even"
}
return false, "Value must be an integer"
}
// Create custom validation rule
rule := engine.ValidationRule{
FieldName: "number",
Rule: engine.Must,
Expected: validateEvenNumber,
Message: stringPtr("Invalid number"),
}
err := rule.Validate(7)
if err != nil {
fmt.Println(err.Message) // Output: Invalid number
}
CI/CD Pipeline
This project includes a comprehensive CI/CD pipeline that supports both GitHub Actions and GitLab CI/CD. The pipeline runs on every push and merge request to the main and develop branches.
Pipeline Stages
- Lint and Format Check: Runs code linting and formatting checks
- Tests: Executes all tests with coverage reporting
- Build: Builds the application for multiple platforms
- Deploy: Optional deployment stage for releases
GitLab CI/CD
The project includes a .gitlab-ci.yml file that provides:
- Automated testing with coverage thresholds (80% minimum)
- Code quality checks with golangci-lint
- Multi-platform builds (Linux, macOS, Windows)
- Security vulnerability scanning
- Coverage reports and build artifacts
- Manual deployment for tagged releases
GitHub Actions
The project also includes GitHub Actions workflows:
.github/workflows/test.yml- Simple test-only workflow.github/workflows/ci.yml- Comprehensive CI/CD pipeline
Running Tests Locally
# Run all tests
make test
# Run tests with coverage
make test-coverage
# Run specific test file
go test -v ./test/rules_test.go
# Run benchmarks
go test -bench=. -benchmem ./test/...
Coverage Requirements
The CI pipeline enforces a minimum test coverage of 80%. Coverage reports are generated and uploaded as artifacts.
Error Handling
The library provides detailed error information through the ValidationError struct:
type ValidationError struct {
Field string
Rule RuleType
Message string
Exception error
ExceptionMessage string
}
Example results
=== Like Validator Examples ===
1. Basic User Validation
------------------------
✅ Valid user passed all validations
❌ Invalid user failed validations (expected):
- Username: Username must be at least 3 characters
- Age: User must be at least 18 years old
- Password: Password must be at least 8 characters
2. Product Validation with Multiple Rules
------------------------------------------
✅ Valid product passed all validations
❌ Invalid product failed validations (expected):
- Name: Product name must be at least 3 characters
- Price: Price must be greater than 0
- Category: Category cannot be 'Unknown'
3. Order Validation
-------------------
✅ Valid order passed all validations
❌ Invalid order failed validations (expected):
- CustomerID: Customer ID must be positive
- TotalAmount: Total amount cannot exceed 100000
4. Custom Validation Functions
------------------------------
❌ User failed validation:
- Password: Password strength validation failed
- Email: Email domain validation failed
❌ User with weak password and disposable email failed validation (expected):
- Password: Password strength validation failed
- Email: Email domain validation failed
5. Complex Validation Scenarios
--------------------------------
Test Case 1:
❌ Failed validations:
- Bio: Bio validation failed
Test Case 2:
❌ Failed validations:
- Age: User must be at least 13 years old
- Bio: Bio validation failed
Test Case 3:
❌ Failed validations:
- Username: Username must be at least 3 characters
- Bio: Bio validation failed
6. Error Handling and Results
------------------------------
Total validation errors: 3
Validation errors:
Error 1:
Field: Username
Rule: NotEmpty
Message: Username is required
Exception: validation failed
Exception Message: Field Username must not be empty
Error 2:
Field: Email
Rule: NotEmpty
Message: Email is required
Exception: validation failed
Exception Message: Field Email must not be empty
Error 3:
Field: Age
Rule: GreaterThan
Message: Age must be positive
Exception: validation failed
Exception Message: Field Age must be greater than 0
✅ All validations passed successfully
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Requirements
- Go 1.23.9 or higher