2011-10-21 8 views

Respuesta

44

Para hacer eso necesita 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) 
} 

Puede hacer lo mismo con un tipo de estructura en lugar de un int. O cualquier otra cosa, realmente. Solo asegúrese de conocer la distinción entre new y make cuando se trata de tipos de mapas y sectores.

+0

publicó una versión de esta respuesta para las estructuras debajo de –

15

Puede usar reflect.Zero() que devolverá la representación del valor cero del tipo de estructura. (Similar a si se hizo var foo StructType) Esto es diferente de reflect.New() ya que éste será asignar dinámicamente la estructura y darle un puntero, similar a new(StructType)

18

Como reflect.New no hace que automáticamente los tipos de referencia utilizados en los campos de struct, usted podría usar algo como lo siguiente para inicializar de forma recursiva los tipos de campo (tenga en cuenta la definición estructura recursiva en este ejemplo):

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

debería 'cambiar ft.Type.Kind()' ser 'cambiar ft.Kind()'? – nos

+0

La variable ft es del tipo StructField, Kind() en sí es un método de reflect.Type struct – Bilal

0

Aquí hay un ejemplo básico como Evan Shaw dio, pero con una estructura:

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) 

} 

por la respuesta de newacct, utilizando Reflect.zero sería:

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 en los fundamentos de la reflexión en marcha.

Cuestiones relacionadas