Thanks for your interest in improving go-validator. This guide covers the
local workflow and the conventions CI enforces.
- Go 1.23 or newer (see
go.mod). golangci-lintv2 for local linting.
git clone https://github.com/syssam/go-validator
cd go-validator
go mod download
go test ./...CI runs the checks below; run them locally first so the PR goes green on the first try.
gofmt -l . # must print nothing
go vet ./...
golangci-lint run ./...
go test -race ./... # the suite must pass under the race detector
go test -cover ./...A one-liner:
gofmt -l . && go vet ./... && golangci-lint run ./... && go test -race ./...- Formatting:
gofmtis mandatory; CI fails on unformatted files. - No panics: validators must return errors, never panic — even on
adversarial input (see
fuzz_test.go). - Thread-safety: validation must be safe to run concurrently. Do not mutate
cached metadata (
field/ValidTag) during validation. Package-level config maps (MessageMap,RuleMap, …) are configured once at startup, not at runtime — useCustomTypeRuleMapfor runtime-safe registration. - Tests are required. Every bug fix needs a regression test that fails
against the old behavior; every new rule needs unit tests. Keep the
allocation-free success path allocation-free (
go test -bench=. -benchmem).
- No-parameter rule (e.g.
distinct): add toRuleMapintypes.go. - Parameter rule (e.g.
min=value): add toParamRuleMapintypes.go. - String pattern rule (e.g.
email): add the pattern topatterns.go, the function tovalidator_string.go, and register it inStringRulesMap. - Add the default message to
MessageMapinmessage.go(and thelang/*files for translations). - Add tests in the matching
*_test.gofile; add a benchmark if the rule does non-trivial work.
Input-facing changes should be fuzzed:
go test -fuzz=FuzzValidateStruct -fuzztime=60s- Bugs: open a GitHub issue with a minimal reproduction.
- Security vulnerabilities: do not open a public issue — follow
SECURITY.md.