claudeandClaude Sonnet 5 4483105a78
CI / test (pull_request) Successful in 43s
docs: positioning README, package doc, usage examples
Closes #3.

- doc.go: package overview -- what a validator is, All vs Collect, errors
  are sentinels, how this compares to validator/v10 (tags+reflection),
  ozzo-validation (Rule interface) and govalidator (IsX helpers), and when
  to pick something else.
- README.md: rewritten from three lines to a positioning intro, a
  "why this and not X" table, a building-blocks table, and a
  "not a fit if" note.
- example_test.go: runnable Example (compose built-ins + a closure),
  Example_collectAll (errors.Is over a joined error), Example_errorsIs
  (sentinel matching, Err as match-anything).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 14:01:03 +01:00
2024-07-19 14:11:34 +01:00
2026-09-07 13:59:59 +01:00
2026-09-07 13:59:59 +01:00
2023-11-19 20:42:48 +00:00
2026-09-07 13:59:59 +01:00
2026-07-05 23:38:45 +01:00
2026-09-07 13:59:59 +01:00
2026-09-07 13:59:59 +01:00
2024-07-11 17:33:18 +01:00
2026-09-07 13:59:59 +01:00
2024-07-19 14:11:53 +01:00
2026-09-07 13:59:59 +01:00
2026-09-07 13:59:59 +01:00

Go Validate

Small, composable value validators for Go. A validator is just a func(T) error — it returns nil or an error. You compose them with All or Collect and drop in plain closures wherever you need something custom. No struct tags, no reflection, no dependencies outside the standard library.

username := validate.All(
	validate.MinLength(3),
	validate.MaxLength(16),
	validate.Chars("abcdefghijklmnopqrstuvwxyz0123456789_"),
	func(s string) error {
		if strings.HasPrefix(s, "_") {
			return errors.New("must not start with an underscore")
		}
		return nil
	},
)

if err := username(input); err != nil {
	// errors.Is(err, validate.ErrDisallowedChars) still works
}

Why this and not one of the established packages

Package Style
go-playground/validator struct tags (validate:"required,email") driven by reflection
go-ozzo/ozzo-validation rules composed in code, through a Rule interface over interface{}
asaskevich/govalidator a bag of IsEmail / IsURL string helpers

This package is the code-composition style (closest to ozzo-validation) with two constraints held on purpose:

  • Validators are ordinary generic functions. In, Equal and the rest are type-checked by the compiler — pass the wrong type and it does not build. The tag/reflection libraries can't do this; they predate generics.
  • Errors are plain sentinels. errors.Is(err, ErrInvalidEmail) composes with the standard errors package. There is no bespoke ValidationErrors type to learn. Err matches any error from the package.

Everything is value-level: there is no struct walker. You wire fields together yourself (a few lines) and decide how to present the result.

Fail fast or collect everything

// stops at the first failure
validate.All(rules...)

// runs every rule, joins the failures with errors.Join;
// errors.Is still matches each one
validate.Collect(rules...)

Building blocks

Group Functions
Compose All, Collect
Presence / equality Required, Equal, In, NotIn
String length & content MinLength, MaxLength, Chars, ExceptChars, Prefix, Suffix, Contains, Match
Formats Email, URL, UUID
Numbers Min, Max, MinFloat32, MaxFloat32, MinFloat64, MaxFloat64
Slices MinSize, MaxSize
Errors Error, NewError, Err

Each returns (or is) a func(T) error, so anything you write with the same shape composes with them.

Not a fit if…

You want struct-tag validation, translated / i18n messages, or a large catalogue of built-in checks (credit cards, ISO codes, CIDRs, …). Use go-playground/validator for that. This package deliberately stays small.

License

MIT. See LICENSE.md.

S
Description
No description provided
Readme
95 KiB
Languages
Go 100%