FAQ
Can I use it on a value or do I need a pointer?
Both work. Check accepts interface{} — pointers are dereferenced automatically, and nil is treated as "nothing to validate" rather than a panic.
govalid.Check(form) // value
govalid.Check(&form) // pointerIf you need a Validate() error method with a pointer receiver to fire, pass a pointer. Value receivers fire either way.
How do I make a field optional but still format-checked?
Skip the required rule. Format-style checkers (email, mobile, …) treat the empty string as valid:
type Form struct {
Backup string `valid:"email"` // empty allowed, must be valid if set
}How do I require a boolean to be true?
Use required. govalid's required interprets a bool field as "non-zero", which means true:
type Terms struct {
Accepted bool `valid:"required" label:"服务条款"`
}How do I validate a slice element-by-element?
Make it a slice of structs and tag the struct's fields. govalid walks elements automatically:
type Item struct {
Name string `valid:"required"`
}
type Order struct {
Items []Item `valid:"required"`
}For []*Item (slice of pointers) per-element validation isn't supported today — use []Item or loop manually.
How do I get a field's original error type back?
Today *ErrContext doesn't expose Unwrap, so type-asserting through errors.As won't reach a Validate() method's underlying error. Two common workarounds:
- Encode the data you need in the error string.
- Return errors via a side channel from
Validate()(e.g. embed them on the form struct itself).
This is a known rough edge — please open an issue if it bites you.
Why do min/max ignore my bool field?
Because they only act on numeric kinds (signed/unsigned int and float). For booleans, prefer required or list:true,false.
Why is equal comparing strings?
equal stringifies both sides with fmt.Sprintf("%v", …). This makes it work across heterogeneous types (int vs string), at the cost of not catching subtle type mismatches. Write a custom checker if you need strict typed equality.
Can I run multiple validators on the same struct?
Yes. govalid is stateless from the caller's perspective — Check can be called repeatedly with the same value. Each call walks the struct afresh.
Is the library safe for use with hot-reloaded checker maps?
Reads of Checkers, errorTemplateChinese, etc. are concurrent-safe as long as no writer is active. If you must mutate at runtime, wrap the mutations in your own mutex and pause traffic while the swap happens.