2011-10-21 4 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型ではなくstruct型でも同じことができます。それとも何か、本当に。地図とスライスのタイプについては、newとmakeの区別を必ず確認してください。

+0

は、 –

15

reflect.Zero()は、struct型のゼロ値の表現を返します。後者は、動的構造体を割り当て、あなたにポインタを与えるよう(あなたが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構造体からのメソッドです – 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) 

} 
再帰的にこれらのフィールドタイプを(この例では、再帰的な構造体の定義に注意)初期化するには、次のようなものを使用Reflect.zeroを使用してnewacctの応答パー

が、それは次のようになります。外出先での反射の基礎に

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

関連する問題