Custom Validation Logic
Implementing Advanced Flag Validation
Custom validation logic allows developers to create sophisticated input checks beyond basic type constraints, enabling complex validation scenarios for command-line applications.
Validation Approaches
Approach |
Complexity |
Use Case |
Function-based Validation |
Low |
Simple rule checking |
Struct-based Validation |
Medium |
Complex object validation |
Middleware Validation |
High |
Comprehensive input processing |
Basic Custom Validation Example
package main
import (
"flag"
"fmt"
"log"
"regexp"
)
type ValidationRule struct {
Validate func(string) bool
ErrorMsg string
}
func validateUsername(username string) bool {
// Custom username validation rules
rules := []ValidationRule{
{
Validate: func(u string) bool { return len(u) >= 3 },
ErrorMsg: "Username must be at least 3 characters long",
},
{
Validate: func(u string) bool {
match, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, u)
return match
},
ErrorMsg: "Username can only contain alphanumeric characters and underscores",
},
}
for _, rule := range rules {
if !rule.Validate(username) {
log.Printf("Validation error: %s", rule.ErrorMsg)
return false
}
}
return true
}
func main() {
username := flag.String("username", "", "User's username")
flag.Parse()
if !validateUsername(*username) {
log.Fatal("Invalid username")
}
fmt.Println("Username validated successfully!")
}
Validation Logic Flowchart
graph TD
A[Input Flag] --> B{First Validation Rule}
B -->|Pass| C{Next Validation Rule}
B -->|Fail| D[Return Error]
C -->|Pass| E{More Rules?}
C -->|Fail| D
E -->|Yes| B
E -->|No| F[Validation Success]
Advanced Validation Techniques
1. Dependency Injection for Validation
type Validator interface {
Validate(input string) bool
}
type UsernameValidator struct {
MinLength int
AllowedChars string
}
func (v *UsernameValidator) Validate(input string) bool {
return len(input) >= v.MinLength &&
regexp.MustCompile(v.AllowedChars).MatchString(input)
}
2. Composable Validation Rules
func composeValidators(validators ...Validator) Validator {
return &CompositeValidator{validators}
}
type CompositeValidator struct {
validators []Validator
}
func (cv *CompositeValidator) Validate(input string) bool {
for _, validator := range cv.validators {
if !validator.Validate(input) {
return false
}
}
return true
}
Best Practices
- Keep validation logic modular and reusable
- Provide clear error messages
- Use interfaces for flexible validation
- Consider performance implications
- Handle edge cases gracefully
- Minimize complex regex operations
- Cache validation results when possible
- Use efficient data structures
- Implement short-circuit validation
At LabEx, we recommend designing flexible and maintainable validation strategies that enhance the robustness of command-line applications.