反思:通过字符串创建结构体

huangapple go评论82阅读模式
英文:

Reflection: Struct by string

问题

假设我有这样一个带有方法的结构体:

package main

import (
	"fmt"
	"reflect"
)

type MyStruct struct {
}

func (a *MyStruct) AAction() {
	fmt.Println("Hello a")
}

现在,如果我想通过字符串调用方法"AAction",我可以使用反射(这样可以工作):

func main() {
	reflect.New(reflect.TypeOf(MyStruct{})).MethodByName("AAction").Call([]reflect.Value{})
}

问题是,我不想将MyStruct{}作为表达式使用,而是作为一个字符串。当然,这样是行不通的:

func main() {
	theStruct := "MyStruct"
	theAction := "AAction"
	reflect.New(reflect.TypeOf(theStruct)).MethodByName(theAction).Call([]reflect.Value{})
}

因为reflect.TypeOf(theStruct)将是一个字符串。我尝试阅读文档,但可惜找不到什么非常有用的信息。

我找到了类似的问题:https://stackoverflow.com/questions/8103617/call-a-struct-and-its-method-by-name-in-go
在接受的答案下,提问者问道:

在我的情况下,问题是我不能声明t的类型为T,它必须以字符串"T"的形式声明为T

得到的回答是:

[...] 我建议在代码中的某个地方将名称与字符串"T"匹配 [...]

这并没有解决问题,因为我仍然需要在某个地方调用MyStruct{}

问题是:有没有办法通过给出结构体的名称作为字符串来使用结构体?(而不是手动将结构体的名称映射到结构体)

使用reflect.TypeOf(MyStruct{})的工作版本:
PlayGround

显然在字符串上调用方法的不工作版本:PlayGround

英文:

Let's assume I have this struct with a method:

package main

import (
	"fmt"
	"reflect"
)

type MyStruct struct {
}

func (a *MyStruct) AAction() {
	fmt.Println("Hello a")
}

Now, if I want to call the method "AAction" by string, I can use reflection (this works):

func main() {
	reflect.New(reflect.TypeOf(MyStruct{})).MethodByName("AAction").Call([]reflect.Value{})
}

The problem is, that I don't want to use MyStruct{} as an expression, but as a string. Of course this doesn't work:

func main() {
	theStruct := "MyStruct"
	theAction := "AAction"
	reflect.New(reflect.TypeOf(theStruct)).MethodByName(theAction).Call([]reflect.Value{})
}

because reflect.Typeof(theStruct) would be a string.
I tried reading through the documentation, sadly, I can't find anything very useful.

I found this similar question: https://stackoverflow.com/questions/8103617/call-a-struct-and-its-method-by-name-in-go
<br /> Under the accepted question, the OP asks:

> The issue in my case Is I cant not declare t is typed T, its must be some how I can declare t typed T by the name of T is string "T"

which gets answered by

> [...] I would suggest to match the name against the string "T" somewhere in your code [...]

which doesn't solve the problem, as I would still need to call MyStruct{} somewhere.

The question is: is there any way to use a struct by giving the name as a string? (without manually mapping the the name of the struct to the struct)

Working version with using reflect.TypeOf(MyStruct{}):
PlayGround<br/>
Not working version, obviously calling the method on a string: PlayGround

答案1

得分: 3

抱歉,你不能这样做。答案是:你不能。没有内置或预初始化的类型名称注册表。

要开始使用反射(reflect包),你需要一个值(所涉及的类型的值)。基于一个string(类型的字符串名称),你无法获取该类型的值,因此你无法开始。

如果你确实想通过string类型名称来实现你想要的功能,你需要在进行操作之前构建自己的“注册表”。

英文:

Sorry, you can't. The answer is: you could not. There is no builtin or pre-initialized registry of type names.

To get started with reflection (reflect package), you need a value (of the type in question). Based on a string (string name of the type), you can't acquire a value of that type, so you can't get started.

If you do want to do what you want only by a string type name, you need to build your own "registry" prior to doing what you want.

huangapple
  • 本文由 发表于 2016年4月5日 19:18:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/36424907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定