I am trying to create my own validator for gin, but I want it to be "generic", so let's say, I want to have an interface IsValid
type IsValid interface {
IsValid() bool
}
, and make some structs to have binding:"IsValid" in some fields that implement that interface.
But I don't know how to write my custom validator to get the field, cast it to the IsValid interface, and then execute the isValid method.
I am using the go-playground validator package: https://github.com/go-playground/validator
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// registering validation for isValid
v.RegisterValidation("isValid", func(fl validator.FieldLevel) bool {
isValidField := // TODO do something to cast it to that interface
return isValidField.IsValid()
})
}
The FieldLevel
type has this method:
// returns current field for validation
Field() reflect.Value
reflect.Value
has this method:
func (v Value) Interface() (i any)
Interface returns v's current value as an interface{}. It is equivalent to:
var i interface{} = (v's underlying value)
It panics if the Value was obtained by accessing unexported struct fields.
You can use a type assertion to utilize an interface{}
/ any
value as a more specific interface like this:
var i interface{} = something
var x = i.(MyInterface)
This will panic if the value i
doesn't implement MyInterface
. To check for that case, the alternate form can be used:
var x, ok = i.(MyInterface)
if ok {
// use x
} else {
// type conversion failed
}
Putting it together, your code would be something like this:
isValidField, ok := fl.Field().Interface().(IsValid)