I have one struct with 2 methods under struct definition, I want to call in other place that use struct's name and method's name as param.
Struct code as following:
type ArticleForm struct {
Name string `required:"true" pattern:"^[A-Za-z0-9\u4e00-\u9fa5]{1,1024}$" valid:"Required;MaxSize(1024)"`
Category []Category `class:"multis" required:"true" valid:"Required" optionqs:"GetCategoryOption"`
Content string `class:"wysiwg_area" required:"true" valid:"Required"`
Tags []Tags `class:"multis_create" optionqs:"GetTagOptions"`
}
Method definition as following:
func (this *ArticleForm) GetTagOptions() []Tags {
return GetTagsOptions(nil)
}
Following is what I want to call:
func main() {
s := "models.ArticleForm"
t := "GetTagOptions"
//following is the question, how can i exec following?
funcall(s,t)
}
How to fulfill the funcall(s,t)
?
Calling a method of some type given by its name is easy (using reflection). See this example:
type My struct{}
func (m My) MyFunc() {
fmt.Println("MyFunc called")
}
func main() {
m := My{}
meth := reflect.ValueOf(m).MethodByName("MyFunc")
meth.Call(nil)
}
Output (try it on the Go Playground):
MyFunc called
"Instantiating" a type given its string name is not possible, because if your code does not explicitly refer to the type, it may not even be included in the executable binary. For details, see Call all functions with special prefix or suffix in Golang; and Splitting client/server code.
A possible workaround is to use some kind of "type-registry" which you populate prior to using it (before you want to create a value by its name). The type registry (which may be a map) may hold reflect.Type
values or factory functions mapped from the type name.
Following the above My
type declaration, a type registry storing reflect.Type
values may look like this (try it on the Go Playground):
registry := map[string]reflect.Type{
"My": reflect.TypeOf((*My)(nil)).Elem(),
}
v := reflect.New(registry["My"]).Elem()
v.MethodByName("MyFunc").Call(nil)
And a registry that stores factory functions could look like this (try it on the Go Playground):
registry := map[string]func() interface{}{
"My": func() interface{} { return My{} },
}
v := registry["My"]()
meth := reflect.ValueOf(v).MethodByName("MyFunc")
meth.Call(nil)