https://github.com/tiendc/go-validator
Intuitive validation library for Golang
https://github.com/tiendc/go-validator
generic go golang validation validator
Last synced: 5 months ago
JSON representation
Intuitive validation library for Golang
- Host: GitHub
- URL: https://github.com/tiendc/go-validator
- Owner: tiendc
- License: mit
- Created: 2023-10-20T12:25:28.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-11-27T14:09:21.000Z (about 1 year ago)
- Last Synced: 2025-04-06T07:37:42.846Z (8 months ago)
- Topics: generic, go, golang, validation, validator
- Language: Go
- Homepage:
- Size: 119 KB
- Stars: 30
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go-plus - go-validator - Validation library using Generics.  (Validation / Utility/Miscellaneous)
- awesome-go-cn - go-validator - validator) (验证 / 实用程序/Miscellaneous)
- awesome-go - tiendc/go-validator
- awesome-go-with-stars - go-validator - Validation library using Generics. (Validation / Utility/Miscellaneous)
- awesome-go - go-validator - Validation library using Generics. (Validation / Utility/Miscellaneous)
- fucking-awesome-go - go-validator - Validation library using Generics. (Validation / Utility/Miscellaneous)
- awesome-go - go-validator - Validation library using Generics. (Validation / Utility/Miscellaneous)
README
[![Go Version][gover-img]][gover] [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![GoReport][rpt-img]][rpt]
# Fast and intuitive validation library for Go
This lib uses the `Is...` validation functions from the [govalidator](https://github.com/asaskevich/govalidator) project.
## Installation
```shell
go get github.com/tiendc/go-validator
```
## Usage
#### General usage
```go
import (
vld "github.com/tiendc/go-validator"
)
type Person struct {
FirstName string
LastName string
Birthdate time.Time
Unemployed bool
Salary uint
Rank string
WorkEmail string
Projects []string
TaskMap map[string]Task
}
var p Person
errs := vld.Validate(
// Validate first and last names separately
vld.StrLen(&p.FirstName, 3, 30).OnError(
vld.SetField("first_name", nil),
vld.SetCustomKey("ERR_VLD_PERSON_FIRST_NAME_INVALID"),
),
vld.StrLen(&p.FirstName, 3, 30).OnError(
vld.SetField("last_name", nil),
vld.SetCustomKey("ERR_VLD_PERSON_LAST_NAME_INVALID"),
),
// OR use this to produce only one error when one of them fails
vld.Group(
vld.StrLen(&p.FirstName, 3, 30),
vld.StrLen(&p.LastName, 3, 30),
).OnError(
vld.SetField("name", nil),
vld.SetCustomKey("ERR_VLD_PERSON_NAME_INVALID"),
),
// Birthdate is optional, but when it's present, it must be within 1950 and now
vld.When(!p.Birthdate.IsZero()).Then(
vld.TimeRange(p.Birthdate, <1950-01-01>, time.Now()).OnError(...),
)
vld.When(!p.Unemployed).Then(
vld.Required(&p.Salary),
// Work email must be valid
vld.StrIsEmail(&p.WorkEmail),
// Rank must be one of the constants
vld.StrIn(&p.Rank, "Employee", "Manager", "Director"),
vld.Case(
vld.When(p.Rank == "Manager").Then(vld.NumGT(&p.Salary, 10000)),
vld.When(p.Rank == "Director").Then(vld.NumGT(&p.Salary, 30000)),
).Default(
vld.NumLT(&p.Salary, 10000),
),
// Projects are optional, but when they are present, they must be unique and sorted
vld.When(len(p.Projects) > 0).Then(
vld.SliceUnique(p.Projects).OnError(...),
vld.SliceSorted(p.Projects).OnError(...),
)
).Else(
// When person is unemployed
vld.NumEQ(&p.Salary, 0),
vld.StrEQ(&p.WorkEmail, ""),
),
// Validate slice elements
vld.Slice(p.Projects).ForEach(func(elem int, index int, validator ItemValidator) {
validator.Validate(
vld.StrLen(&elem, 10, 30).OnError(
vld.SetField(fmt.Sprintf("projects[%d]", index), nil),
vld.SetCustomKey("ERR_VLD_PROJECT_NAME_INVALID"),
),
)
}),
// Validate map entries
vld.Map(p.TaskMap).ForEach(func(k string, v Task, validator ItemValidator) {
validator.Validate(
vld.StrLen(&v.Name, 10, 30).OnError(
vld.SetField(fmt.Sprintf("taskMap[%s].name", k), nil),
vld.SetCustomKey("ERR_VLD_TASK_NAME_INVALID"),
),
)
}),
// OTHER FUNCTIONS
// Pass if at least one of the validations passes
vld.OneOf(
// List of validations
),
// Pass if exact one of the validations passes
vld.ExactOneOf(
// List of validations
),
// Pass if none of the validations passes
vld.NotOf(
// List of validations
),
)
for _, e := range errs {
detail, warnErr := e.BuildDetail()
fmt.Printf("%+v\n", detail)
}
```
#### Error message localization
- Method 1: inline localization (not recommended)
```go
errs := Validate(
NumLTE(&p.Age, 40).OnError(
// Override the default template in english
SetTemplate("Tuổi nhân viên phải nhỏ hơn hoặc bằng {{.Max}}"),
),
)
for _, e := range errs {
detail, warnErr := e.BuildDetail()
fmt.Printf("%+v\n", detail)
}
```
- Method 2: using another localization lib (recommended)
```go
// Supposed you have 2 files defining error messages
// In `error_messages.en`:
// ERR_VLD_EMPLOYEE_AGE_TOO_BIG = "Employee {{.EmployeeName}} has age bigger than {{.Max}}"
// In `error_messages.vi`:
// ERR_VLD_EMPLOYEE_AGE_TOO_BIG = "Nhân viên {{.EmployeeName}} có tuổi lớn hơn {{.Max}}"
errs := Validate(
NumLTE(&p.Age, 40).OnError(
// Custom param (the default template doesn't have this one)
SetParam("EmployeeName", p.Name),
// Custom key to define custom template to use
SetCustomKey("ERR_VLD_EMPLOYEE_AGE_TOO_BIG"),
),
)
for _, e := range errs {
errKey := e.CustomKey()
errParams : = e.Params() // or e.ParamsWithFormatter()
errorMsg := translationFunction(errKey, errParams) // You need to provide this function
fmt.Printf("%+v\n", errorMsg)
}
```
#### Custom error param formatter
```go
errs := Validate(
NumLT(&budget, 1000000).OnError(
SetField("Budget", nil),
),
)
// e.BuildDetail() may produce message `Budget must be less than 1000000`,
// but you may want a message like: `Budget must be less than 1,000,000`.
// Let's use a custom formatter
errs := Validate(
NumLT(&budget, 1000000).OnError(
SetField("Budget", nil),
SetNumParamFormatter(NewDecimalFormatFunc('.', ',', "%f")),
),
)
```
## Contributing
- You are welcome to make pull requests for new functions and bug fixes.
## License
- [MIT License](LICENSE)
[doc-img]: https://pkg.go.dev/badge/github.com/tiendc/go-validator
[doc]: https://pkg.go.dev/github.com/tiendc/go-validator
[gover-img]: https://img.shields.io/badge/Go-%3E%3D%201.20-blue
[gover]: https://img.shields.io/badge/Go-%3E%3D%201.20-blue
[ci-img]: https://github.com/tiendc/go-validator/actions/workflows/go.yml/badge.svg
[ci]: https://github.com/tiendc/go-validator/actions/workflows/go.yml
[cov-img]: https://codecov.io/gh/tiendc/go-validator/branch/main/graph/badge.svg
[cov]: https://codecov.io/gh/tiendc/go-validator
[rpt-img]: https://goreportcard.com/badge/github.com/tiendc/go-validator
[rpt]: https://goreportcard.com/report/github.com/tiendc/go-validator