2011-10-21 104 views

回答

44

为了做到这一点,您需要reflect

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来做同样的事情。或者其他任何东西,真的。当涉及到map和slice类型时,一定要知道new和make之间的区别。

+0

发布了此答案的一个版本,对于 –

15

您可以使用reflect.Zero()这将返回结构类型的零值的表示形式。 (类似,如果你没有var foo StructType)这是reflect.New()因为后者将动态分配的结构,给你一个指针,类似的不同来new(StructType)

18

由于reflect.New不会自动在结构领域中引用类型,你可以使用类似下面的递归初始化这些字段类型(注意在这个例子中,递归结构定义):

package main 

import (
    "fmt" 
    "reflect" 
) 

type Config struct { 
    Name string 
    Meta struct { 
     Desc string 
     Properties map[string]string 
     Users []string 
    } 
} 

func initializeStruct(t reflect.Type, v reflect.Value) { 
    for i := 0; i < v.NumField(); i++ { 
    f := v.Field(i) 
    ft := t.Field(i) 
    switch ft.Type.Kind() { 
    case reflect.Map: 
     f.Set(reflect.MakeMap(ft.Type)) 
    case reflect.Slice: 
     f.Set(reflect.MakeSlice(ft.Type, 0, 0)) 
    case reflect.Chan: 
     f.Set(reflect.MakeChan(ft.Type, 0)) 
    case reflect.Struct: 
     initializeStruct(ft.Type, f) 
    case reflect.Ptr: 
     fv := reflect.New(ft.Type.Elem()) 
     initializeStruct(ft.Type.Elem(), fv.Elem()) 
     f.Set(fv) 
    default: 
    } 
    } 
} 

func main() { 
    t := reflect.TypeOf(Config{}) 
    v := reflect.New(t) 
    initializeStruct(t, v.Elem()) 
    c := v.Interface().(*Config) 
    c.Meta.Properties["color"] = "red" // map was already made! 
    c.Meta.Users = append(c.Meta.Users, "srid") // so was the slice. 
    fmt.Println(v.Interface()) 
} 
+0

以下的结构,应该'switch ft.Type.Kind()'是'switch ft.Kind()'? – nos

+0

ft变量的类型是StructField,Kind()本身是reflect.Type的一个方法struct – Bilal

0

这里有一个基本的例子像埃文·肖给了,但有一个结构:

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 

This is a great article在去反思的基础知识。

相关问题