{"id":31164262,"url":"https://github.com/sivchari/govalid","last_synced_at":"2025-09-19T07:57:11.035Z","repository":{"id":296521885,"uuid":"987054584","full_name":"sivchari/govalid","owner":"sivchari","description":"Up to 45x faster 🚀 Auto generate type-safe validation code for structs based on markers.","archived":false,"fork":false,"pushed_at":"2025-09-16T04:54:50.000Z","size":760,"stargazers_count":217,"open_issues_count":21,"forks_count":12,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-16T06:33:12.379Z","etag":null,"topics":["abstract-syntax-tree","autogenerated","error-handling","go","golang","translation","type-safe","validation"],"latest_commit_sha":null,"homepage":"https://sivchari.github.io/govalid/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sivchari.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-20T14:03:25.000Z","updated_at":"2025-09-13T06:23:08.000Z","dependencies_parsed_at":"2025-05-31T21:05:07.879Z","dependency_job_id":"4807e919-4c18-4963-bb6b-14350c459b8f","html_url":"https://github.com/sivchari/govalid","commit_stats":null,"previous_names":["sivchari/govalid"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/sivchari/govalid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sivchari%2Fgovalid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sivchari%2Fgovalid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sivchari%2Fgovalid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sivchari%2Fgovalid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sivchari","download_url":"https://codeload.github.com/sivchari/govalid/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sivchari%2Fgovalid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275771771,"owners_count":25525892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["abstract-syntax-tree","autogenerated","error-handling","go","golang","translation","type-safe","validation"],"created_at":"2025-09-19T07:57:05.378Z","updated_at":"2025-09-19T07:57:10.421Z","avatar_url":"https://github.com/sivchari.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assets/govalid-icon.svg\" alt=\"govalid\" width=\"128\" height=\"128\"\u003e\n  \u003ch1\u003egovalid\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eBlazing fast, zero-allocation, type-safe validation for Go\u003c/strong\u003e\u003c/p\u003e\n\n  ![Go Version](https://img.shields.io/badge/Go-1.21+-blue.svg)\n  ![License](https://img.shields.io/badge/license-MIT-green.svg)\n  ![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)\n  [![Go Report Card](https://goreportcard.com/badge/github.com/sivchari/govalid)](https://goreportcard.com/report/github.com/sivchari/govalid)\n\u003c/div\u003e\n\n---\n\n## 🚀 Overview\n\ngovalid generates **type-safe validation code** from struct field markers. No reflection, no runtime overhead, just blazing fast validation.\n\n## ⚡ Why govalid?\n\n### 🎯 Performance Benefits\n- **Zero allocations**: All validation functions perform zero heap allocations\n- **5x to 44x faster**: Significantly outperforms reflection-based validators\n- **Compile-time optimization**: Generated code is optimized by the Go compiler\n\n### 👨‍💻 Developer Experience\n- **Type safety**: Validation functions are generated with proper types, eliminating runtime reflection\n- **Early error detection**: Invalid validation rules are caught during code generation, not at runtime\n- **No runtime dependencies**: Generated code has minimal external dependencies\n\n### 🔧 Comprehensive Go Support\n- **Full collection support**: Maps and channels work with size validators (not supported by most libraries)\n- **CEL expressions**: Common Expression Language support for complex validation logic\n- **Go zero-value semantics**: Proper handling of Go's zero values and nil states\n- **Unicode-aware**: String validators properly handle Unicode characters\n\n## 📊 Performance Comparison\n\n\u003cdiv align=\"center\"\u003e\n\n| Feature | govalid | Reflection Validators |\n|:-------:|:-------:|:--------------------:|\n| **Performance** | `~1-14ns, 0 allocs` | `~50-700ns, 0-5 allocs` |\n| **Type Safety** | ✅ Generated functions | ❌ Runtime reflection |\n| **Collections** | `slice, array, map, channel` | `slice, array only` |\n| **Dependencies** | ✅ Minimal | ❌ Heavy runtime deps |\n| **Error Detection** | ✅ During code generation | ❌ Runtime |\n| **CEL Support** | ✅ Full support | ❌ Limited/None |\n\n\u003c/div\u003e\n\n## 📦 Installation\n\n\nInstall the `govalid` command-line tool by one of supported ways:\n\nUsing `go install`:\n\n# Defaults to latest @ and version to install specific release\n```bash\ngo install github.com/sivchari/govalid/cmd/govalid\n```\n\nOr:\n\n```bash\n# Clone the repository\ngit clone https://github.com/sivchari/govalid.git\n\n# Navigate to the project directory\ncd govalid\n\n# Install the tool\ngo install ./...\n```\n\n\nVerify the installation:\n\n```bash\ngovalid -h\n```\n\n## 🎯 Quick Start\n\n### 1. Define Your Struct\n```go\n// Add validation markers above your struct\n// +govalid:required\ntype Person struct {\n    Name  string `json:\"name\"`\n    // +govalid:email\n    Email string `json:\"email\"`\n}\n```\n\n### 2. Generate Validation Code\n```bash\ngovalid generate\n```\n\nThis generates validation code like:\n\n```go\n// Code generated by govalid; DO NOT EDIT.\nimport (\n\t\"errors\"\n\t\"github.com/sivchari/govalid\"\n\tgovaliderrors \"github.com/sivchari/govalid/validation/errors\"\n\t\"github.com/sivchari/govalid/validation/validationhelper\"\n)\n\nvar (\n\t// ErrNilPerson is returned when the Person is nil.\n\tErrNilPerson = errors.New(\"input Person is nil\")\n\n\t// ErrPersonNameRequiredValidation is returned when the Name is required but not provided.\n\tErrPersonNameRequiredValidation = govaliderrors.ValidationError{Reason: \"field Name is required\", Path: \"Person.Name\", Type: \"required\"}\n\n\t// ErrPersonEmailEmailValidation is the error returned when the field is not a valid email address.\n\tErrPersonEmailEmailValidation = govaliderrors.ValidationError{Reason: \"field Email must be a valid email address\", Path: \"Person.Email\", Type: \"email\"}\n)\n\nvar _ govalid.Validator = (*Person)(nil)\n\nfunc ValidatePerson(t *Person) error {\n\tif t == nil {\n\t\treturn ErrNilPerson\n\t}\n\n\tvar errs govaliderrors.ValidationErrors\n\n\tif t.Name == \"\" {\n\t\terr := ErrPersonNameRequiredValidation\n\t\terr.Value = t.Name\n\t\terrs = append(errs, err)\n\t}\n\n\tif !validationhelper.IsValidEmail(t.Email) {\n\t\terr := ErrPersonEmailEmailValidation\n\t\terr.Value = t.Email\n\t\terrs = append(errs, err)\n\t}\n\n\tif len(errs) \u003e 0 {\n\t\treturn errs\n\t}\n\treturn nil\n}\n\nfunc (p *Person) Validate() error {\n\treturn ValidatePerson(p)\n}\n```\n\n### 3. Use Generated Validators\n\n```go\nfunc main() {\n\tp := \u0026Person{Name: \"John\", Email: \"invalid-email\"}\n\n\tif err := ValidatePerson(p); err != nil {\n\t\tlog.Printf(\"Validation failed: %v\", err)\n\t\t// Output: Validation failed: field Email must be a valid email address\n\t\tif errors.Is(err, ErrPersonEmailEmailValidation) {\n\t\t\tlog.Printf(\"Email validation failed, handle error as needed: %v\", err)\n\t\t}\n\t}\n}\n```\n\n#### 3.1 Handle multiple validation errors\n\nIn case of multiple validation errors, `govalid` generated validators will aggregate all errors and return a list\nof structs that implement error interface.\n\n```go\nfunc main() {\n\tp := \u0026Person{Name: \"\", Email: \"invalid-email\"}\n\n\tif err := ValidatePerson(p); err != nil {\n\t\tlog.Printf(\"Validation failed: %v\", err)\n\n\t\tif errors.Is(err, ErrPersonEmailEmailValidation) {\n\t\t\tlog.Printf(\"First email error\", err)\n\t\t}\n\n\t\tif errors.Is(err, ErrPersonNameRequiredValidation) {\n\t\t\tlog.Printf(\"Second required error %v\", err)\n\t\t}\n\t}\n}\n```\n\n#### 3.2 Validator Interface\n```go\nfunc main() {\n\tp := \u0026Person{Name: \"John\", Email: \"invalid-email\"}\n\n\tif err := p.Validate(); err != nil {\n\t\tlog.Printf(\"Validation failed: %v\", err)\n\t}\n}\n```\n\nThe generated `Validate()` method enables seamless integration with HTTP middleware:\n\n```go\nimport (\n\t\"net/http\"\n\t\"github.com/sivchari/govalid/validation/middleware\"\n)\n\nfunc CreatePersonHandler(w http.ResponseWriter, r *http.Request) {\n\tw.Write([]byte(\"OK\"))\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/person\", middleware.ValidateRequest[*Person](CreatePersonHandler))\n\thttp.ListenAndServe(\":8080\", nil)\n}\n```\n\n## 🔧 Advanced Features\n\n### Struct-Level Validation\nApply validation rules to entire structs:\n\n```go\n// All fields will be validated as required\n// +govalid:required\ntype Person struct {\n    Name  string\n    Email string\n    Age   int\n}\n```\n\n### CEL Expression Support\nUse Common Expression Language for complex validation:\n\n```go\ntype User struct {\n    // +govalid:cel=value \u003e= 18 \u0026\u0026 value \u003c= 120\n    Age int\n    // +govalid:cel=value \u003e= this.Age\n    RetirementAge int\n}\n```\n\n### Collection Support\nValidate maps, channels, slices, and arrays:\n\n```go\n// +govalid:maxitems=10\ntype UserList struct {\n    Users    []User           // slice support\n    UserMap  map[string]User  // map support  \n    UserChan chan User        // channel support\n}\n```\n\n## 📝 Supported Markers\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e📖 View Complete Marker Reference\u003c/strong\u003e\u003c/summary\u003e\n\nFor a complete reference of all supported markers, see [MARKERS.md](MARKERS.md).\n\n**Core Validators:**\n- `required` - Field must not be zero value\n- `gt`, `gte`, `lt`, `lte` - Numeric comparisons\n- `maxlength`, `minlength` - String length validation\n- `maxitems`, `minitems` - Collection size validation\n- `enum` - Enumeration validation\n- `email`, `url`, `uuid`, `numeric` - Format validation\n\n**Advanced:**\n- `cel` - Common Expression Language support\n- Struct-level markers\n- Custom validation logic\n\n\u003c/details\u003e\n\n## 🚀 Performance Benchmarks\n\ngovalid consistently outperforms reflection-based validators by **5x to 44x**:\n\n\u003cdiv align=\"center\"\u003e\n\n| Validator | govalid | go-playground | Improvement |\n|:---------:|:-------:|:-------------:|:-----------:|\n| Required | `1.9ns` | `85.5ns` | **44.2x** |\n| GT/LT | `1.9ns` | `63.0ns` | **32.5x** |\n| MaxLength | `15.7ns` | `73.5ns` | **4.7x** |\n| Email | `38.2ns` | `649.4ns` | **17.0x** |\n\n*All with **0 allocations** vs competitors' 0-5 allocations*\n\n\u003c/div\u003e\n\n[📊 View Complete Benchmarks](test/benchmark/README.md)\n\n### 🔧 Development Setup\n\nFor contributors, install lefthook to enable pre-commit checks:\n\n```bash\nmake install-lefthook\n```\n\nBecause of this, lefthook is installed, then the code-base would be checked automatically before each commit, ensuring code quality and consistency.\n\n## 📄 License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003csub\u003eBuilt with ❤️ for the Go community\u003c/sub\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsivchari%2Fgovalid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsivchari%2Fgovalid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsivchari%2Fgovalid/lists"}