govalid generates type-safe validation code from struct field markers. No reflection, no runtime overhead, just blazing fast validation.
- Zero allocations: All validation functions perform zero heap allocations
- 5x to 44x faster: Significantly outperforms reflection-based validators
- Compile-time optimization: Generated code is optimized by the Go compiler
- Type safety: Validation functions are generated with proper types, eliminating runtime reflection
- Early error detection: Invalid validation rules are caught during code generation, not at runtime
- No runtime dependencies: Generated code has minimal external dependencies
- Full collection support: Maps and channels work with size validators (not supported by most libraries)
- CEL expressions: Common Expression Language support for complex validation logic
- Go zero-value semantics: Proper handling of Go's zero values and nil states
- Unicode-aware: String validators properly handle Unicode characters
| Feature | govalid | Reflection Validators |
|---|---|---|
| Performance | ~1-14ns, 0 allocs |
~50-700ns, 0-5 allocs |
| Type Safety | β Generated functions | β Runtime reflection |
| Collections | slice, array, map, channel |
slice, array only |
| Dependencies | β Minimal | β Heavy runtime deps |
| Error Detection | β During code generation | β Runtime |
| CEL Support | β Full support | β Limited/None |
Install the govalid command-line tool by one of supported ways:
Using go install:
go install github.com/sivchari/govalid/cmd/govalidOr:
# Clone the repository
git clone https://github.com/sivchari/govalid.git
# Navigate to the project directory
cd govalid
# Install the tool
go install ./...Verify the installation:
govalid -h// Add validation markers above your struct
// +govalid:required
type Person struct {
Name string `json:"name"`
// +govalid:email
Email string `json:"email"`
}govalid generateThis generates validation code like:
// Code generated by govalid; DO NOT EDIT.
import (
"errors"
"github.com/sivchari/govalid"
govaliderrors "github.com/sivchari/govalid/validation/errors"
"github.com/sivchari/govalid/validation/validationhelper"
)
var (
// ErrNilPerson is returned when the Person is nil.
ErrNilPerson = errors.New("input Person is nil")
// ErrPersonNameRequiredValidation is returned when the Name is required but not provided.
ErrPersonNameRequiredValidation = govaliderrors.ValidationError{Reason: "field Name is required", Path: "Person.Name", Type: "required"}
// ErrPersonEmailEmailValidation is the error returned when the field is not a valid email address.
ErrPersonEmailEmailValidation = govaliderrors.ValidationError{Reason: "field Email must be a valid email address", Path: "Person.Email", Type: "email"}
)
var _ govalid.Validator = (*Person)(nil)
func ValidatePerson(t *Person) error {
if t == nil {
return ErrNilPerson
}
var errs govaliderrors.ValidationErrors
if t.Name == "" {
err := ErrPersonNameRequiredValidation
err.Value = t.Name
errs = append(errs, err)
}
if !validationhelper.IsValidEmail(t.Email) {
err := ErrPersonEmailEmailValidation
err.Value = t.Email
errs = append(errs, err)
}
if len(errs) > 0 {
return errs
}
return nil
}
func (p *Person) Validate() error {
return ValidatePerson(p)
}func main() {
p := &Person{Name: "John", Email: "invalid-email"}
if err := ValidatePerson(p); err != nil {
log.Printf("Validation failed: %v", err)
// Output: Validation failed: field Email must be a valid email address
if errors.Is(err, ErrPersonEmailEmailValidation) {
log.Printf("Email validation failed, handle error as needed: %v", err)
}
}
}In case of multiple validation errors, govalid generated validators will aggregate all errors and return a list
of structs that implement error interface.
func main() {
p := &Person{Name: "", Email: "invalid-email"}
if err := ValidatePerson(p); err != nil {
log.Printf("Validation failed: %v", err)
if errors.Is(err, ErrPersonEmailEmailValidation) {
log.Printf("First email error", err)
}
if errors.Is(err, ErrPersonNameRequiredValidation) {
log.Printf("Second required error %v", err)
}
}
}func main() {
p := &Person{Name: "John", Email: "invalid-email"}
if err := p.Validate(); err != nil {
log.Printf("Validation failed: %v", err)
}
}The generated Validate() method enables seamless integration with HTTP middleware:
import (
"net/http"
"github.com/sivchari/govalid/validation/middleware"
)
func CreatePersonHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}
func main() {
http.HandleFunc("/person", middleware.ValidateRequest[*Person](CreatePersonHandler))
http.ListenAndServe(":8080", nil)
}Apply validation rules to entire structs:
// All fields will be validated as required
// +govalid:required
type Person struct {
Name string
Email string
Age int
}Use Common Expression Language for complex validation:
type User struct {
// +govalid:cel=value >= 18 && value <= 120
Age int
// +govalid:cel=value >= this.Age
RetirementAge int
}Validate maps, channels, slices, and arrays:
// +govalid:maxitems=10
type UserList struct {
Users []User // slice support
UserMap map[string]User // map support
UserChan chan User // channel support
}π View Complete Marker Reference
For a complete reference of all supported markers, see MARKERS.md.
Core Validators:
required- Field must not be zero valuegt,gte,lt,lte- Numeric comparisonsmaxlength,minlength- String length validationmaxitems,minitems- Collection size validationenum- Enumeration validationemail,url,uuid,numeric- Format validation
Advanced:
cel- Common Expression Language support- Struct-level markers
- Custom validation logic
govalid consistently outperforms reflection-based validators by 5x to 44x:
| Validator | govalid | go-playground | Improvement |
|---|---|---|---|
| Required | 1.9ns |
85.5ns |
44.2x |
| GT/LT | 1.9ns |
63.0ns |
32.5x |
| MaxLength | 15.7ns |
73.5ns |
4.7x |
38.2ns |
649.4ns |
17.0x |
All with 0 allocations vs competitors' 0-5 allocations
For contributors, install lefthook to enable pre-commit checks:
make install-lefthookBecause of this, lefthook is installed, then the code-base would be checked automatically before each commit, ensuring code quality and consistency.
MIT License - see LICENSE file for details.