I have some special type in Golang what represent a string with Validate method.
type string128 string
func (s *string128) Validate() error {
...
return nil
}
There is structs have fields like the following:
type Strings1 struct {
str1 string
str2 string128
str3 string128
...
strN+1 string128
strN+2 string
}
type Strings2 struct {
str1 string
str2 string128
str3 string128
...
strN+1 string128
strN+2 string
}
I want to make a function where I can pass them and if the field have a Validate() function call it.
What I have done:
func validateStruct(a interface{}) error {
v := reflect.ValueOf(a)
t := reflect.TypeOf(a)
for i := 0; i < v.NumField(); i++ {
err := reflect.TypeOf(v.Field(i).Interface()).MethodByName("Validate").Call(...)
}
return nil
}
But it is do a lots of panic.
I found the problem. The reflect.TypeOf(v.Field(i).Interface()).MethodByName("Validate")
see the function only if the Validate function doesn't have pointer receiver so if I modify the Validate function of the string128 to func (s string128) Validate() error
, it is working.
Final solution
func validateStruct(a interface{}) error {
v := reflect.ValueOf(a)
for i := 0; i < v.NumField(); i++ {
if _, ok := reflect.TypeOf(v.Field(i).Interface()).MethodByName("Validate"); ok {
err := reflect.ValueOf(v.Field(i).Interface()).MethodByName("Validate").Call([]reflect.Value{})
if !err[0].IsNil() {
return err[0].Interface().(error)
}
}
}
return nil
}