Skip to content

Performance

govalid uses pure reflection — no code generation, no caches that need warming up. The numbers below were measured on an Apple M1 Pro with Go 1.26 (go test -bench=. -benchmem):

text
BenchmarkCheck_Simple_Valid-10      745966     1655 ns/op    1136 B/op    29 allocs/op
BenchmarkCheck_Simple_Invalid-10    713349     1644 ns/op    1160 B/op    31 allocs/op
BenchmarkCheck_Rich_Valid-10        262418     4748 ns/op    3216 B/op    73 allocs/op
BenchmarkParseRules-10             2852902      412 ns/op     520 B/op    14 allocs/op

For a 10-field "rich" struct (mobile, email, length & range checks) that's about 210k validations/second per core with no escape-hatch optimizations.

What costs how much?

OperationCost
parseRules per tag~400 ns / 14 allocs
Per checker invocationlow ns each, regex-driven checkers vary
Reflective field walkingdominates allocations
Localized message renderingone strings.NewReplacer per non-trivial template

Hot paths and tips

  • Compile regex once. Built-in patterns are package-level regexp.MustCompile. Custom checkers should follow the same pattern.
  • Reuse struct types. parseRules caches per-tag rule slices for the duration of a single Check call, but it does not cache across calls.
  • Validate once per request. govalid is fast enough to call inline in HTTP handlers; you don't need a "validation cache".
  • Avoid massive list: rules. Each entry is compared with fmt.Sprintf("%v", value). For a few dozen values, fine. For thousands, switch to a custom checker that uses a map[string]struct{}.

Concurrency

Check is safe to call concurrently. The package-level state that matters for hot paths (Checkers, the locale template maps) is not synchronized for writes — register custom checkers and templates at program startup, before goroutines start hitting Check.

The library has been exercised under go test -race with both shared-struct and independent-struct concurrent workloads.

Fuzz coverage

The repository ships two fuzz targets:

sh
go test -run=^$ -fuzz=FuzzCheck     -fuzztime=10s ./...
go test -run=^$ -fuzz=FuzzParseRules -fuzztime=10s ./...

Combined, these have logged millions of executions without producing a panic. If you spot a crashing input, please file an issue with the seed.

Released under the MIT License.