英文:
How to call method by its string name with string struct name?
问题
我有一个结构体,在结构体定义下有两个方法,我想在其他地方调用这个结构体的名称和方法的名称作为参数。
结构体代码如下:
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"`
}
方法定义如下:
func (this *ArticleForm) GetTagOptions() []Tags {
return GetTagsOptions(nil)
}
以下是我想要调用的代码:
func main() {
s := "models.ArticleForm"
t := "GetTagOptions"
//以下是问题,如何执行以下代码?
funcall(s,t)
}
如何实现 funcall(s,t)
?
英文:
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)
?
答案1
得分: 23
调用给定名称的某个类型的方法很容易(使用反射)。看看这个例子:
type My struct{}
func (m My) MyFunc() {
fmt.Println("MyFunc called")
}
func main() {
m := My{}
meth := reflect.ValueOf(m).MethodByName("MyFunc")
meth.Call(nil)
}
输出结果(在Go Playground上尝试):
MyFunc called
根据其字符串名称来“实例化”一个类型是不可能的,因为如果你的代码没有明确引用该类型,它甚至可能不会包含在可执行二进制文件中。有关详细信息,请参阅https://stackoverflow.com/questions/37384473/call-all-functions-with-special-prefix-or-suffix-in-golang/37384665#37384665和https://stackoverflow.com/questions/38875016/splitting-client-server-code/38875901#38875901。
一种可能的解决方法是使用某种“类型注册表”,在使用之前填充它(在您想要按名称创建值之前)。类型注册表(可以是一个映射)可以保存reflect.Type值或从类型名称映射的工厂函数。
根据上述My
类型声明,存储reflect.Type
值的类型注册表可能如下所示(在Go Playground上尝试):
registry := map[string]reflect.Type{
"My": reflect.TypeOf((*My)(nil)).Elem(),
}
v := reflect.New(registry["My"]).Elem()
v.MethodByName("MyFunc").Call(nil)
而存储工厂函数的注册表可能如下所示(在Go Playground上尝试):
registry := map[string]func() interface{}{
"My": func() interface{} { return My{} },
}
v := registry["My"]()
meth := reflect.ValueOf(v).MethodByName("MyFunc")
meth.Call(nil)
英文:
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 https://stackoverflow.com/questions/37384473/call-all-functions-with-special-prefix-or-suffix-in-golang/37384665#37384665; and https://stackoverflow.com/questions/38875016/splitting-client-server-code/38875901#38875901.
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论