Skip to content

Repository files navigation

✅ GoValidate — Struct Validation for Go

Tag-based validation with 20+ built-in rules, nested struct support, and custom rules — zero dependencies.

GoLicense

GoValidate provides declarative struct validation using Go struct tags. Supports nested structs, slices, custom rules, and JSON field names — all with zero external dependencies.


📦 Features

FeatureDescription
Struct Tagsvalidate:"required,min=3,max=100"
20+ Built-in Rulesrequired, min, max, email, url, ip, alpha, regex...
Nested StructsRecursive validation with dot-notation errors
Slice ValidationValidates each element: Items[0].Name
Custom RulesRegisterRule("phone", fn)
JSON NamesUses json tag name in error messages
Error Maperrs.Map()map[string][]string
Cross-fieldoneof, numeric comparisons
Zero DependenciesOnly Go standard library + reflect

🚀 Quick Start

go get github.com/kzxl/govalidate
package main
import (
"fmt""github.com/kzxl/govalidate"
)
typeUserstruct {
Namestring`json:"name" validate:"required,min=3,max=50"`Emailstring`json:"email" validate:"required,email"`Ageint`json:"age" validate:"gte=0,lte=150"`Passwordstring`json:"password" validate:"required,min=8"`Rolestring`json:"role" validate:"oneof=admin user moderator"`
}
funcmain() {
user:=User{
Name: "Jo", // too shortEmail: "invalid", // bad emailAge: -1, // negative
}
errs:=govalidate.Validate(user)
iferrs.HasErrors() {
for_, e:=rangeerrs.Errors {
fmt.Printf(" %s [%s]: %s\n", e.Field, e.Rule, e.Message)
}
// Output:// name [min]: must be at least 3 characters// email [email]: must be a valid email address// age [gte]: must be >= 0// password [required]: is required
}
// Error map for API responsesfmt.Println(errs.Map())
// map[name:[must be at least 3 characters] email:[must be a valid email] ...]
}

📖 Built-in Rules

RuleExampleDescription
requiredvalidate:"required"Field must not be zero value
minvalidate:"min=3"Min length (string/slice) or min value (number)
maxvalidate:"max=100"Max length or value
lenvalidate:"len=5"Exact length
gt / gtevalidate:"gt=0"Greater than / greater than or equal
lt / ltevalidate:"lte=100"Less than / less than or equal
emailvalidate:"email"Valid email format
urlvalidate:"url"Valid URL with scheme and host
ipvalidate:"ip"Valid IPv4 or IPv6
alphavalidate:"alpha"Letters only
alphanumvalidate:"alphanum"Letters and numbers only
numericvalidate:"numeric"Numeric characters only
lowercasevalidate:"lowercase"Must be all lowercase
uppercasevalidate:"uppercase"Must be all uppercase
containsvalidate:"contains=keyword"Must contain substring
startswithvalidate:"startswith=Hello"Must start with prefix
endswithvalidate:"endswith=!"Must end with suffix
oneofvalidate:"oneof=admin user"Must be one of listed values
regexvalidate:"regex=^\\d{3}$"Must match regex pattern
datetimevalidate:"datetime=2006-01-02"Must parse with Go layout

🔧 Custom Rules

govalidate.RegisterRule("phone", func(v reflect.Value, paramstring) string {
ifv.Kind() !=reflect.String { return"" }
if!phoneRegex.MatchString(v.String()) {
return"must be a valid phone number"
}
return""
})
typeContactstruct {
Phonestring`validate:"required,phone"`
}

🏗️ Nested Struct & Slice Validation

typeOrderstruct {
CustomerCustomer`validate:"required"`Items []Item`validate:"min=1"`
}
typeItemstruct {
Namestring`validate:"required"`Priceint`validate:"gt=0"`
}
// Errors:// customer.name: is required// Items[0].Price: must be > 0

📄 License

Apache License 2.0 — See LICENSE for details.


✅ Validate structs, the Go way.

About

Struct validation for Go with 20+ built-in rules, nested struct support, and custom rules

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages