2011-10-21 29 views

Odpowiedz

44

Aby to zrobić, potrzebujesz 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) 
} 

Możesz zrobić to samo z typem struktury zamiast z int. Lub cokolwiek innego, naprawdę. Po prostu upewnij się, że znasz rozróżnienie między nowymi i make, jeśli chodzi o typy map i plasterków.

+0

opublikował wersję tej odpowiedzi dla struktur poniżej –

15

Można użyć reflect.Zero(), która zwróci reprezentację wartości zerowej typu struct. (Podobny do jeśli nie var foo StructType) Różni się to od reflect.New() jako ostatni będzie dynamicznie przydziela struct i daje wskaźnik, podobny do new(StructType)

18

As reflect.New nie automatycznie dokonać typów referencyjnych stosowanych w dziedzinach struct, można używać czegoś takiego do rekurencyjnie zainicjować te typy pól (zauważ rekurencyjną definicję struct w tym przykładzie):

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

powinien "przełącznik ft.Type.Kind()' być 'przełącznik ft.Kind()'? – nos

+0

ft zmienna jest typu StructField, sama Kind() jest metodą z reflect.Type struct – Bilal

0

Oto prosty przykład jak Evan Shaw dał, ale z struct:

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) 

} 

Per odpowiedzi newacct, wykorzystując Reflect.zero byłoby:

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 na podstawach odbicie w podróży.

Powiązane problemy