checkerlint is a static analyzer for Checker's checkers (and validate fallback) struct tags. Struct tags are opaque string literals, so a typo'd checker name, a checker applied to a field of the wrong type, or a cross-field checker (eq-field, after-field, before-field, required-if, required-unless) whose target field was renamed all compile fine and only fail — sometimes silently — when that code path runs. checkerlint catches all three at build/lint time instead.
type Registration struct {
Password string `checkers:"trim required"`
ConfirmPassword string `checkers:"required eq-field:Passwrd"` // typo: no such field
Age int `checkers:"email"` // email is string-only
}./registration.go:3:2: checkerlint: eq-field references field "Passwrd", which doesn't exist on this struct
./registration.go:4:2: checkerlint: email requires a string, but the field's type is int
It knows the built-in checker vocabulary from the version of github.com/cinar/checker/v2 it's built against, plus any custom checker registered in the analyzed packages via a checker.RegisterMaker/RegisterFieldMaker call with a string-literal name. It can't see a checker registered only at runtime in a different package, or under a name built from a non-literal expression.
go install github.com/cinar/checker/v2/checkerlint/cmd/checkerlint@latestStandalone, with the same flags and package patterns as go vet:
checkerlint ./...As a go vet tool:
go vet -vettool=$(which checkerlint) ./...As a custom analyzer in golangci-lint (v2's module plugin system):
# .golangci.yml
version: "2"
linters:
settings:
custom:
checkerlint:
type: module
path: github.com/cinar/checker/v2/checkerlint
settings: {}
linters-settings:
gomodguard: {}Consult golangci-lint's module plugin documentation for the exact build step your golangci-lint version expects; module-plugin support and its build workflow have changed across golangci-lint releases.
- Unknown checker names — every token in a
checkers/validatetag must be a registered checker/normalizer, a registered field-relative checker,omitempty, or a name your own code registers viaRegisterMaker/RegisterFieldMakerwith a string literal. - Type compatibility — a well-scoped set of built-in checkers that panic at runtime on the wrong kind (string-only checkers like
email,trim,url, ...; numeric-only checkersgt/gte/lt/lte) are checked against the tagged field's type, including through one level of pointer indirection and through a slice/array/map's element type for item-level tokens. - Cross-field targets —
eq-field,after-field,before-field,required-if, andrequired-unlessmust reference a field that actually exists on the same struct (including, on a best-effort basis, embedded/anonymous fields).
This library is free to use, modify, and distribute under the terms of the MIT license found in the LICENSE file of the parent Checker repository.