You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
With helper functions we can make common types of validation much easier. I
propose two categories of helper functions:
Value Assertion: Helpers which assert a specific state/property of a given
value, returning a boolean to indicate if the given value meets the condition
or not. These functions should typically have a name which starts with Is, Has, or similar words. For example: IsNil(), HasLen()
Validation: Helpers which will perform a specific type of check against a
value, and return nil on success, or a *Error on failure. Under the hood
they'll use Value Assertion functions, along with custom logic as needed.
These functions should typically have a name which starts with Require or Allow. For example: RequireField(), RequireLen(), AllowFieldWhen()
Value Assertion helpers
Value assertion helpers simply return a boolean value indicating if the given
value meets the condition of the helper or not. These can be used directly in
custom Validate() functions, and they are also used within validation helper
functions too.
Functions
Below is rough list of value assertion helpers I think are useful, please
suggest changes to this list as you see fit.
IsNil(v interface{}) bool — Checks if given value is nil via reflection.
IsEmpty(v interface{}) bool — Checks if given value is equal to the
type's zero value, or for slices that it is a non-nil empty slice.
IsBlank(v interface{}) bool — Checks if given value returns true from
either of IsNil() or IsEmpty().
HasLen(v interface{}, n int) bool — Check if given value has a length of
exactly n.
HasMinLen(v interface{}, min int) bool — Check if given value has a
length equal to or greater than min.
HasMaxLen(v interface{}, max int) bool — Check if given value has a
length equal to or less than max.
HasLenBetween(v interface{}, min, max int) bool — Check if given value
has a length equal to or greater than min and equal to or less than max.
Validation helpers
Validation helpers verify if given values meets specific conditions, returning nil on success, and a *Error if it fails that describes why the validation
failed.
There are two variants of all validation helpers, the "direct validation" and
"field validation". The direct variants validates the given value directly, and
does not set a Field value on the returned *Error object. While a field
validation helper accepts an instance of a struct, and one or more fields as
strings, and performs the validation against the given field(s) on the given
struct, and sets the Field value as needed on the returned *Error.
Translations / i18n
While I believe providing multi-language translations for built-in validation
helpers is probably outside the scope of this project right now, we should
strive to make translations possible and hopefully easy to implement if/when
needed.
As such, I propose we create *Validation structs for each type of validation,
which contains all the input fields needed to produce a human readable error
message, along with a Error() string function that produces the English
language string for the error.
For example, using the RequireLenBetween(v interface{}, min, max int) error
helper described below, we could have a struct like this:
typeRequireLenBetweenValidationstruct {
MinintMaxint
}
func (s*RequireLenBetweenValidation) Error() string {
returnfmt.Sprintf(
"must have a length equal to or greater than %d "+"and equal to or less than %d",
s.Min, s.Max,
)
}
This enables Validate() functions to return *RequireLenBetweenValidation
instances directly which will be wrapped up in a *Error with the field set
correctly.
RequireFieldLenBetween(s interface{}, field string, min, max int) error helper
described below, would simply wrap the validation error struct in a *Error
directly with the field set accordingly.
This should allow easy translation by performing type assertions on the Err
value for each type of validation error you want to support translating.
Though effectively it means validation translations happen on he returned errors
after executing validation, rather than it being built-in to the validation
package itself. It simply exposes enough information about each validation error
to implement your own humanly readable error in any language you see fit.
Functions
Below is rough list of validation helpers I think are useful, please suggest
changes to this list as you see fit.
Require
Require(v interface{}) error
RequireField(s interface{}, field string) error
Validates value is not nil or empty as determined by IsBlank().
Error message on failure:
"is required"
RequireNotNil
RequireNotNil(v interface{}) error
RequireFieldNotNil(s interface{}, field string) error
Validates value is not nil as determined by IsNil().
Error message on failure:
"must not be nil"
RequireNotEmpty
RequireNotEmpty(v interface{}) error
RequireFieldNotEmpty(s interface{}, field string) error
Validates value is not empty as determined by IsEmpty().
Error message on failure:
"must not be empty"
RequireLen
RequireLen(v interface{}, n int) error
RequireFieldLen(s interface{}, field string, n int) error
Validates value has a length of exactly n.
Error message on failure:
"must have a length of exactly <n>"
RequireMinLen
RequireMinLen(v interface{}, min int) error
RequireFieldMinLen(s interface{}, field string, min int) error
Validates value has a length equal to or greater than min.
Error message on failure:
"must have a length equal to or greater than <min>"
RequireMaxLen
RequireMaxLen(v interface{}, max int) error
RequireFieldMaxLen(s interface{}, field string, max int) error
Validates value has a length equal to or less than max.
Error message on failure:
"must have a length equal to or greater than <max>"
RequireLenBetween
RequireLenBetween(v interface{}, min, max int) error
RequireFieldLenBetween(s interface{}, field string, min, max int) error
Validates that the given value has a length equal to or greater than min and
equal to or less than max.
"must have a length equal to or greater than <min> and equal to or less than <max>"
With helper functions we can make common types of validation much easier. I
propose two categories of helper functions:
value, returning a boolean to indicate if the given value meets the condition
or not. These functions should typically have a name which starts with
Is
,Has
, or similar words. For example:IsNil()
,HasLen()
value, and return nil on success, or a
*Error
on failure. Under the hoodthey'll use Value Assertion functions, along with custom logic as needed.
These functions should typically have a name which starts with
Require
orAllow
. For example:RequireField()
,RequireLen()
,AllowFieldWhen()
Value Assertion helpers
Value assertion helpers simply return a boolean value indicating if the given
value meets the condition of the helper or not. These can be used directly in
custom
Validate()
functions, and they are also used within validation helperfunctions too.
Functions
Below is rough list of value assertion helpers I think are useful, please
suggest changes to this list as you see fit.
IsNil(v interface{}) bool
— Checks if given value is nil via reflection.IsEmpty(v interface{}) bool
— Checks if given value is equal to thetype's zero value, or for slices that it is a non-nil empty slice.
IsBlank(v interface{}) bool
— Checks if given value returns true fromeither of
IsNil()
orIsEmpty()
.HasLen(v interface{}, n int) bool
— Check if given value has a length ofexactly
n
.HasMinLen(v interface{}, min int) bool
— Check if given value has alength equal to or greater than
min
.HasMaxLen(v interface{}, max int) bool
— Check if given value has alength equal to or less than
max
.HasLenBetween(v interface{}, min, max int) bool
— Check if given valuehas a length equal to or greater than
min
and equal to or less thanmax
.Validation helpers
Validation helpers verify if given values meets specific conditions, returning
nil
on success, and a*Error
if it fails that describes why the validationfailed.
There are two variants of all validation helpers, the "direct validation" and
"field validation". The direct variants validates the given value directly, and
does not set a
Field
value on the returned*Error
object. While a fieldvalidation helper accepts an instance of a struct, and one or more fields as
strings, and performs the validation against the given field(s) on the given
struct, and sets the
Field
value as needed on the returned*Error
.Translations / i18n
While I believe providing multi-language translations for built-in validation
helpers is probably outside the scope of this project right now, we should
strive to make translations possible and hopefully easy to implement if/when
needed.
As such, I propose we create
*Validation
structs for each type of validation,which contains all the input fields needed to produce a human readable error
message, along with a
Error() string
function that produces the Englishlanguage string for the error.
For example, using the
RequireLenBetween(v interface{}, min, max int) error
helper described below, we could have a struct like this:
This enables
Validate()
functions to return*RequireLenBetweenValidation
instances directly which will be wrapped up in a
*Error
with the field setcorrectly.
RequireFieldLenBetween(s interface{}, field string, min, max int) error
helperdescribed below, would simply wrap the validation error struct in a
*Error
directly with the field set accordingly.
This should allow easy translation by performing type assertions on the
Err
value for each type of validation error you want to support translating.
Though effectively it means validation translations happen on he returned errors
after executing validation, rather than it being built-in to the validation
package itself. It simply exposes enough information about each validation error
to implement your own humanly readable error in any language you see fit.
Functions
Below is rough list of validation helpers I think are useful, please suggest
changes to this list as you see fit.
Require
Require(v interface{}) error
RequireField(s interface{}, field string) error
Validates value is not nil or empty as determined by
IsBlank()
.Error message on failure:
"is required"
RequireNotNil
RequireNotNil(v interface{}) error
RequireFieldNotNil(s interface{}, field string) error
Validates value is not nil as determined by
IsNil()
.Error message on failure:
"must not be nil"
RequireNotEmpty
RequireNotEmpty(v interface{}) error
RequireFieldNotEmpty(s interface{}, field string) error
Validates value is not empty as determined by
IsEmpty()
.Error message on failure:
"must not be empty"
RequireLen
RequireLen(v interface{}, n int) error
RequireFieldLen(s interface{}, field string, n int) error
Validates value has a length of exactly
n
.Error message on failure:
"must have a length of exactly <n>"
RequireMinLen
RequireMinLen(v interface{}, min int) error
RequireFieldMinLen(s interface{}, field string, min int) error
Validates value has a length equal to or greater than
min
.Error message on failure:
"must have a length equal to or greater than <min>"
RequireMaxLen
RequireMaxLen(v interface{}, max int) error
RequireFieldMaxLen(s interface{}, field string, max int) error
Validates value has a length equal to or less than
max
.Error message on failure:
"must have a length equal to or greater than <max>"
RequireLenBetween
RequireLenBetween(v interface{}, min, max int) error
RequireFieldLenBetween(s interface{}, field string, min, max int) error
Validates that the given value has a length equal to or greater than
min
andequal to or less than
max
."must have a length equal to or greater than <min> and equal to or less than <max>"
RequireOneOf
RequireOneOf(s interface{}, fields ...string) error
Validates that only one of specified
fields
on structs
has a non-nil ornon-empty value as determined by
IsBlank()
.Error message on failure:
"exactly one of 'Field1', 'Field2', or 'Field3' must be specified"
RequireExactlyNOf
RequireExactlyNOf(s interface{}, n int, fields ...string) error
Validates that exactly
n
of specifiedfields
on structs
has a non-nil ornon-empty value as determined by
IsBlank()
.Error message on failure:
"exactly <n> of 'Field1', 'Field2', or 'Field3' must be specified"
RequireFieldWhen
RequireFieldWhen(s interface{}, field, other string, v interface{})
When field
other
on structs
is equal to value inv
, validates that fieldfield
on structs
is not nil or empty as determined byIsBlank()
.Error message when
other
is"Type"
andv
is"Book"
:"is required when Type='Book'"
AllowFieldWhen
AllowFieldWhen(s interface{}, field, other string, v interface{})
When field
other
on structs
is not equal to value inv
, validates thatfield
field
on structs
is nil or empty as determined byIsBlank()
.Effectively prohibiting setting field
field
if fieldother
is not equal tov
.Error message when
other
is"Type"
andv
is"Book"
:"is only allowed when Type='Book'"
The text was updated successfully, but these errors were encountered: