如何在Go中从运行时的类型创建结构的新实例?

如何在Go中从运行时的类型创建结构的新实例?,go,reflection,go-reflect,Go,Reflection,Go Reflect,在Go中,如何在运行时从对象的类型创建对象的实例?我想您也需要先获得对象的实际类型 我正在尝试进行延迟实例化以节省内存。为了做到这一点,您需要反射 package main import ( "fmt" "reflect" ) func main() { // one way is to have a value of the type you want already a := 1 // reflect.New works kind of like

在Go中,如何在运行时从对象的类型创建对象的实例?我想您也需要先获得对象的实际
类型


我正在尝试进行延迟实例化以节省内存。

为了做到这一点,您需要
反射

package main

import (
    "fmt"
    "reflect"
)

func main() {
    // one way is to have a value of the type you want already
    a := 1
    // reflect.New works kind of like the built-in function new
    // We'll get a reflected pointer to a new int value
    intPtr := reflect.New(reflect.TypeOf(a))
    // Just to prove it
    b := intPtr.Elem().Interface().(int)
    // Prints 0
    fmt.Println(b)

    // We can also use reflect.New without having a value of the type
    var nilInt *int
    intType := reflect.TypeOf(nilInt).Elem()
    intPtr2 := reflect.New(intType)
    // Same as above
    c := intPtr2.Elem().Interface().(int)
    // Prints 0 again
    fmt.Println(c)
}

可以用结构类型而不是int或其他任何类型来做同样的事情。当涉及到映射和切片类型时,请确保知道new和make之间的区别。

您可以使用
reflect.Zero()
,它将返回结构类型的零值表示形式。(类似于如果您执行了
var foo StructType
)这不同于
reflect.New()
,因为后者将动态分配结构并给您一个指针,类似于
New(StructType)
as
reflect。New
不会自动在结构字段中使用引用类型,您可以使用以下类似的方法递归初始化这些字段类型(请注意本例中的递归结构定义):

主程序包
进口(
“fmt”
“反映”
)
类型配置结构{
名称字符串
元结构{
描述字符串
属性映射[字符串]字符串
用户[]字符串
}
}
func initializeStruct(t reflect.Type,v reflect.Value){
对于i:=0;i
下面是一个基本示例,如Evan Shaw给出的示例,但有一个结构:

package main

import (
    "fmt"
    "reflect"
)

func main() {

    type Product struct {
        Name  string
        Price string
    }

    var product Product
    productType := reflect.TypeOf(product)       // this type of this variable is reflect.Type
    productPointer := reflect.New(productType)   // this type of this variable is reflect.Value. 
    productValue := productPointer.Elem()        // this type of this variable is reflect.Value.
    productInterface := productValue.Interface() // this type of this variable is interface{}
    product2 := productInterface.(Product)       // this type of this variable is product

    product2.Name = "Toothbrush"
    product2.Price = "2.50"

    fmt.Println(product2.Name)
    fmt.Println(product2.Price)

}
根据newacct的响应,使用Reflect.zero将是:

   var product Product
   productType := reflect.TypeOf(product)       // this type of this variable is reflect.Type
   productValue := reflect.Zero(productType)    // this type of this variable is reflect.Value
   productInterface := productValue.Interface() // this type of this variable is interface{}
   product2 := productInterface.(Product)       // the type of this variable is Product

关于围棋中反射的基础知识

您不需要
reflect
,如果factory模式共享相同的界面,您可以轻松实现这一点:

package main

import (
    "fmt"
)

// Interface common for all classes
type MainInterface interface {
    GetId() string
}

// First type of object
type FirstType struct {
    Id string
}

func (ft *FirstType) GetId() string {
    return ft.Id
}

// FirstType factory
func InitializeFirstType(id string) MainInterface {
    return &FirstType{Id: id}
}


// Second type of object
type SecondType struct {
    Id string
}

func (st *SecondType) GetId() string {
    return st.Id
}

// SecondType factory
func InitializeSecondType(id string) MainInterface {
    return &SecondType{Id: id}
}


func main() {
    // Map of strings to factories
    classes := map[string]func(string) MainInterface{
        "first": InitializeFirstType,
        "second": InitializeSecondType,
    }

    // Create a new FirstType object with value of 10 using the factory
    newObject := classes["first"]("10")

    // Show that we have the object correctly created
    fmt.Printf("%v\n", newObject.GetId())


    // Create a new SecondType object with value of 20 using the factory
    newObject2 := classes["second"]("20")

    // Show that we have the object correctly created
    fmt.Printf("%v\n", newObject2.GetId())
}

switch ft.Type.Kind()
应该是
switch ft.Kind()
?ft变量的类型是StructField,Kind()本身是reflect.Type struct中的一个方法如果有指向结构的指针呢?(
&Config{}
而不是
Config{}
)@Xeoncross,这在最后一个
案例
中介绍,其中字段的类型与
reflect.Ptr
@fuzzybear3965进行比较,谢谢,自从我的问题发布后,答案已更新。下面是结构的答案版本。我是否必须基于某个对象或指向该对象的指针对其进行实例化?我正在使用struct。我希望它获取结构本身(不是它的实例化对象),获取它的类型,并使用反射实例化它。或者,我想以某种方式使用reflect.New(something)实例化一个对象,而不只是以通常的方式实例化结构,因为应该从函数参数向代码中传递某些内容。我该怎么做呢?product2:=productInterface.(Product)的意义是什么?当一个人可以product2:=Product{}时,问题是如果不键入Product,我就无法将json.Unmarshal转换为这样的值。所以对于json包来说,这似乎毫无意义。
package main

import (
    "fmt"
)

// Interface common for all classes
type MainInterface interface {
    GetId() string
}

// First type of object
type FirstType struct {
    Id string
}

func (ft *FirstType) GetId() string {
    return ft.Id
}

// FirstType factory
func InitializeFirstType(id string) MainInterface {
    return &FirstType{Id: id}
}


// Second type of object
type SecondType struct {
    Id string
}

func (st *SecondType) GetId() string {
    return st.Id
}

// SecondType factory
func InitializeSecondType(id string) MainInterface {
    return &SecondType{Id: id}
}


func main() {
    // Map of strings to factories
    classes := map[string]func(string) MainInterface{
        "first": InitializeFirstType,
        "second": InitializeSecondType,
    }

    // Create a new FirstType object with value of 10 using the factory
    newObject := classes["first"]("10")

    // Show that we have the object correctly created
    fmt.Printf("%v\n", newObject.GetId())


    // Create a new SecondType object with value of 20 using the factory
    newObject2 := classes["second"]("20")

    // Show that we have the object correctly created
    fmt.Printf("%v\n", newObject2.GetId())
}