实例化新的类型(Golang)

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

Instance new Type (Golang)

问题

有人可以告诉我如何通过字符串创建一个新的 Type 实例吗?使用反射吗?

有一些示例,但它们是针对旧版本(Go 1 之前的版本)的语言的。[:(]

英文:

Can anyone tell me how to create a new instance of Type from a string? Reflect?

There are examples but they are for the older (pre Go 1 versions) of the language [:(]

答案1

得分: 33

如果我正确理解你的问题,你想知道如何在只有类型名称的情况下创建一个对象。例如,你可能有一个字符串"MyStruct",你想创建一个这种类型的对象。

不幸的是,这在Go语言中并不容易实现,因为Go是一种静态类型语言,链接器会消除无用的代码(或内联部分代码)。所以,你的最终可执行文件可能甚至不包含"MyStruct"的代码。

但是,你可以手动维护一个全局的map[string]reflect.Type。例如,在定义这些可发现类型的包的init()函数中初始化这个map。这也会告诉编译器你正在使用这些类型。然后,你可以使用这个map来查找你想要创建的类型的reflect.Type,并使用reflect.New来获取一个指向该类型的新对象的指针(存储为reflect.Value)。你可以使用以下代码将对象提取为接口:

reflect.New(yourtype).Elem().Interface()

Elem()将解引用指针,Interface()将返回反射值作为interface{}。有关更多详细信息,请参阅反射法则

PS:可能有一种更好的方式来组织你的程序,它甚至不需要使用反射,并且可以让编译器捕获更多的错误。例如,你考虑过使用工厂方法吗?另一种简单的解决方案可能是维护一个map[string]func() interface{},其中包含可以调用以创建具有该名称的新对象的函数。

英文:

So, if I understand your question correctly, you are asking about how you can create an object when you just have the name of the type as string. So, for example, you might have a string "MyStruct" and you want to create an object of this type.

Unfortunately, that's not easily possible because Go is a statically typed language and the linker will eliminate dead code (or inline parts of it). So, there is no guarantee, that your final executable will even contain the code of "MyStruct".

You can however, maintain a global map[string]reflect.Type manually. For example by initializing this map in the init() function of your packages which defines such discover-able types. This will also tell the compiler that you are using the types. Afterwards, you can use this map to look up the reflect.Type of the type you want to create and use reflect.New to get a pointer to a new object of that type (stored as a reflect.Value). You can extract the object into an interface with something like this:

reflect.New(yourtype).Elem().Interface()

Elem() will de-reference the pointer and Interface() will return the reflected value as an interface{}. See The Laws of Reflection for further details.

PS: There might be a better way to structure your program which doesn't even require reflection and which let the compiler catch more errors. Have you considered using a factory method for example? An other easy solution might be to maintain a map[string]func() interface{} of functions which can be invoked to create a new object with that name.

答案2

得分: 6

具有预定义构造函数的工厂可以基于类似以下的内容:

package main

import (
	"fmt"
)

type Creator func() interface{}

type A struct {
	a int
}

type B struct {
	a bool
}

func NewA() interface{} {
	return new(A)
}

func NewB() interface{} {
	return new(B)
}

func main() {
	m := map[string]Creator{}
	m["A"] = NewA
	m["B"] = NewB
	for k, v := range m {
		fmt.Printf("%v -> %v\n", k, v())
	}
}
英文:

Factory with predefined constructors can be based on something like:

<!-- language: lang-go -->

package main

import (
	&quot;fmt&quot;
)

type Creator func() interface{}

type A struct {
	a int
}

type B struct {
	a bool
}

func NewA() interface{} {
	return new(A)
}

func NewB() interface{} {
	return new(B)
}

func main() {
	m := map[string]Creator{}
	m[&quot;A&quot;] = NewA
	m[&quot;B&quot;] = NewB
	for k, v := range m {
		fmt.Printf(&quot;%v -&gt; %v\n&quot;, k, v())
	}
}

huangapple
  • 本文由 发表于 2012年4月18日 21:16:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/10210188.html
匿名

发表评论

匿名网友

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

确定