Skip to content

Extending Valgo with custom validators

While all validators in Golang provide a Passing(...) function, which allows you to use a custom validator function, Valgo also allows you to create your own validator.

With this functionality Valgo can be extended with Validator libraries, which we encourage the community to do.

For example, let’s say we want to create a validation for the following ID struct, where a user must provide at least one property.

The struct to validate:

// Type to validate
type ID struct {
Phone string
Email string
}

the custom validator code:

// The custom validator type
type ValidatorID struct {
context *valgo.ValidatorContext
}
// The custom validator implementation of `valgo.Validator`
func (validator *ValidatorID) Context() *valgo.ValidatorContext {
return validator.context
}
// Here is the function that passes the value to the custom validator
func IDValue(value ID, nameAndTitle ...string) *ValidatorID {
return &ValidatorID{context: valgo.NewContext(value, nameAndTitle...)}
}
// The Empty rule implementation
func (validator *ValidatorID) Empty(template ...string) *ValidatorID {
validator.context.Add(
func() bool {
return len(strings.Trim(validator.context.Value().(ID).Phone, " ")) == 0 &&
len(strings.Trim(validator.context.Value().(ID).Email, " ")) == 0
},
v.ErrorKeyEmpty, template...)
return validator
}
// It would be possible to create a rule NotEmpty() instead of Empty(), but if you add a Not() function then your validator will be more flexible.
func (validator *ValidatorID) Not() *ValidatorID {
validator.context.Not()
return validator
}

using our validator:

val := v.Is(IDValue(ID{}, "id").Not().Empty())
out, _ := json.MarshalIndent(val.Error(), "", " ")
fmt.Println(string(out))

output:

{
"identification": [
"Id can't be empty"
]
}