https://github.com/sivchari/govalid
Up to 45x faster 🚀 Auto generate type-safe validation code for structs based on markers.
https://github.com/sivchari/govalid
abstract-syntax-tree autogenerated error-handling go golang translation type-safe validation
Last synced: 4 months ago
JSON representation
Up to 45x faster 🚀 Auto generate type-safe validation code for structs based on markers.
- Host: GitHub
- URL: https://github.com/sivchari/govalid
- Owner: sivchari
- License: mit
- Created: 2025-05-20T14:03:25.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-09-16T04:54:50.000Z (4 months ago)
- Last Synced: 2025-09-16T06:33:12.379Z (4 months ago)
- Topics: abstract-syntax-tree, autogenerated, error-handling, go, golang, translation, type-safe, validation
- Language: Go
- Homepage: https://sivchari.github.io/govalid/
- Size: 742 KB
- Stars: 217
- Watchers: 2
- Forks: 12
- Open Issues: 21
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
govalid
Blazing fast, zero-allocation, type-safe validation for Go



[](https://goreportcard.com/report/github.com/sivchari/govalid)
---
## 🚀 Overview
govalid generates **type-safe validation code** from struct field markers. No reflection, no runtime overhead, just blazing fast validation.
## ⚡ Why govalid?
### 🎯 Performance Benefits
- **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
### 👨💻 Developer Experience
- **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
### 🔧 Comprehensive Go Support
- **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
## 📊 Performance Comparison
| 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 |
## 📦 Installation
Install the `govalid` command-line tool by one of supported ways:
Using `go install`:
# Defaults to latest @ and version to install specific release
```bash
go install github.com/sivchari/govalid/cmd/govalid
```
Or:
```bash
# 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:
```bash
govalid -h
```
## 🎯 Quick Start
### 1. Define Your Struct
```go
// Add validation markers above your struct
// +govalid:required
type Person struct {
Name string `json:"name"`
// +govalid:email
Email string `json:"email"`
}
```
### 2. Generate Validation Code
```bash
govalid generate
```
This generates validation code like:
```go
// 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)
}
```
### 3. Use Generated Validators
```go
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)
}
}
}
```
#### 3.1 Handle multiple validation errors
In case of multiple validation errors, `govalid` generated validators will aggregate all errors and return a list
of structs that implement error interface.
```go
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)
}
}
}
```
#### 3.2 Validator Interface
```go
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:
```go
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)
}
```
## 🔧 Advanced Features
### Struct-Level Validation
Apply validation rules to entire structs:
```go
// All fields will be validated as required
// +govalid:required
type Person struct {
Name string
Email string
Age int
}
```
### CEL Expression Support
Use Common Expression Language for complex validation:
```go
type User struct {
// +govalid:cel=value >= 18 && value <= 120
Age int
// +govalid:cel=value >= this.Age
RetirementAge int
}
```
### Collection Support
Validate maps, channels, slices, and arrays:
```go
// +govalid:maxitems=10
type UserList struct {
Users []User // slice support
UserMap map[string]User // map support
UserChan chan User // channel support
}
```
## 📝 Supported Markers
📖 View Complete Marker Reference
For a complete reference of all supported markers, see [MARKERS.md](MARKERS.md).
**Core Validators:**
- `required` - Field must not be zero value
- `gt`, `gte`, `lt`, `lte` - Numeric comparisons
- `maxlength`, `minlength` - String length validation
- `maxitems`, `minitems` - Collection size validation
- `enum` - Enumeration validation
- `email`, `url`, `uuid`, `numeric` - Format validation
**Advanced:**
- `cel` - Common Expression Language support
- Struct-level markers
- Custom validation logic
## 🚀 Performance Benchmarks
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** |
| Email | `38.2ns` | `649.4ns` | **17.0x** |
*All with **0 allocations** vs competitors' 0-5 allocations*
[📊 View Complete Benchmarks](test/benchmark/README.md)
### 🔧 Development Setup
For contributors, install lefthook to enable pre-commit checks:
```bash
make install-lefthook
```
Because of this, lefthook is installed, then the code-base would be checked automatically before each commit, ensuring code quality and consistency.
## 📄 License
MIT License - see [LICENSE](LICENSE) file for details.
---
Built with ❤️ for the Go community