创建新类型的实例 (Golang)

20

有人能告诉我如何从字符串创建Type的新实例吗?通过反射?

虽然有例子,但它们是针对较旧版本的语言(Go 1之前的版本)[:(]


2
请稍微澄清一下你的问题,我不太清楚。最后的括号后面似乎也不完整。 - zzzz
2个回答

33

如果我理解你的问题正确,你想知道如何在只有类型名称的字符串时创建对象。例如,您可能有一个字符串"MyStruct",希望创建该类型的对象。

不幸的是,在Go中这是不容易实现的,因为它是一种静态类型语言,链接器将消除死代码(或其中的行内部分)。因此,不能保证最终的可执行文件甚至包含"MyStruct"的代码。

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

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

Elem()会引用指针,而Interface()则将反射的值作为interface{}返回。请参阅Reflection法则了解更多细节。

PS: 可能有更好的程序结构方式,不需要使用反射,这样编译器可以捕获更多错误。你考虑过使用工厂方法模式吗?另一种简单的解决方案可能是维护一个map[string]func() interface{}函数映射表,通过调用相应名称的函数来创建新对象。


2
你会如何在Go中实现工厂方法? - Jon L.

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())
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接