Golang parameter validation: drawbacks of go-playground/validator and its replacement checker

liangyaopei
3 min readDec 14, 2020

--

Parameter validation in Golang, go-playground/validator is mostly used (gin framework uses valudator v8/v9).

However, the main drawback of go-playground/validator is that writing validation logic into tags of Golang struct, which is invasive and hard to read.

To solve the drawback, I wrote checker, as a replacement of go-playground/validator. Checker can used for struct or non-sturct validation in Golang.

Examples: compare tags with Rule

Package validtor uses tag to validate, while checker uses Rule . The correspondence between tag and Rule can be found in README.

Examples of using checker is here, including cross filed comparasion in struct, element validation of Slice/Array/Map .

Customized validation Rule

Using validator

Customized validator of playground/validator is a bit complicated, below is the official example:

Using checker

Using checker, users don’t need to write tags inside struct, and the validation logic is more readable. More examples can be foune here.

Customized error message

Using validator

Custiomizing error message in validator is not easy, it needs to use translator. Below is the official example:

Using checker

checker can customized error prompt when adding rule.

func (c *ruleChecker) Add(rule Rule, prompt string) {
c.rules = append(c.rules, rule)
c.prompts = append(c.prompts, prompt)
}

For example, prompt is user-defined message returned when parameter cannot pass rule.

ch.Add(rule, "value is not awesome")
isValid, prompt, errMsg := ch.Check(s)

Easy for checker, hard for validator

The main drawback of validator is, validation rule is attached to fields in struct via tag, which is intrusive, and hard to read the validation logic.

validation sturct of third party

package thrid_partytype Param struct{
Age `validate:"min=18,max=80"`
}

In user’s package, try to change min to 20, validator can not change the validation rule, as we cannot change the struct layout outside our packages.

package mainfunc validate(p thrid_party.Param)(isValid bool){
....
}

If use checker, the rule is simpler:

rule := checker.NewRangeRuleInt("Age", 20, 80)
checker.Add(rule, "invlaid age")

Because validation rule of checker is decoupled from struct, which makes changes validation rule easy.

validate the length of linkedlist

The example is here.

type list struct {
Name *string
Next *list `validate:"nonzero"`
}

To validate the length of linkedlist, requiring the first node’s Next cannot be nil. validator cannot do this, for the same tag is attached to the same field.

If use checker

name := "list"
node1 := list{Name: &name, Next: nil}
lists := list{Name: &name, Next: &node1}
listChecker := checker.NewChecker()
nameRule := checker.NewLengthRule("Next.Name", 1, 20)
listChecker.Add(nameRule, "invalid info name")

Length can be defined by Next.Name

--

--

No responses yet