Obtenir pointeur vers la valeur à l'aide de la réflexion

J'ai une fonction qui parcourt tous les champs d'une interface passé comme paramètre. Afin d'atteindre cet objectif est, je suis l'aide de la réflexion. Le problème est que je ne sais pas comment faire pour obtenir l'adresse d'un non-pointeur de champ. Voici un exemple:

type Z struct {
    Id int
}

type V struct {
    Id int
    F Z
}

type T struct {
    Id int
    F V
}

Le code ci-dessus représente mon test de structures. Maintenant, voici la fonction qui traverse une structure et des listes de détails à ce sujet:

func InspectStruct(o interface{}) {
val := reflect.ValueOf(o)
if val.Kind() == reflect.Interface && !val.IsNil() {
elm := val.Elem()
if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
val = elm
}
}
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
address := "not-addressable"
if valueField.Kind() == reflect.Interface && !valueField.IsNil() {
elm := valueField.Elem()
if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
valueField = elm
}
}
if valueField.Kind() == reflect.Ptr {
valueField = valueField.Elem()
}
if valueField.CanAddr() {
address = fmt.Sprint(valueField.Addr().Pointer())
}
fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\t, Field type: %v\t, Field kind: %v\n", typeField.Name, 
valueField.Interface(), address, typeField.Type, valueField.Kind())
if valueField.Kind() == reflect.Struct {
InspectStruct(valueField.Interface())
}
}
}

Et voici le test après l'instanciation de la structure/initialisation:

t := new(T)
t.Id = 1
t.F = *new(V)
t.F.Id = 2
t.F.F = *new(Z)
t.F.F.Id = 3
InspectStruct(t)

Et enfin la sortie de InspectStruct appel:

Field Name: Id,  Field Value: 1,     Address: 408125440 , Field type: int   , Field kind: int
Field Name: F,   Field Value: {2 {3}},   Address: 408125444 , Field type: main.V    , Field kind: struct
Field Name: Id,  Field Value: 2,     Address: not-addressable   , Field type: int   , Field kind: int
Field Name: F,   Field Value: {3},   Address: not-addressable   , Field type: main.Z    , Field kind: struct
Field Name: Id,  Field Value: 3,     Address: not-addressable   , Field type: int   , Field kind: int

Comme vous pouvez le voir, je suis en utilisant la récursivité, de sorte que si l'un des champs est un struct type puis-je appeler InspectStruct.
Mon problème est que si tous les champs ont été initialisé pour l'ensemble de la structure en "t" de la hiérarchie, je ne suis pas en mesure d'obtenir l'adresse de tout le terrain situé à plus de profondeur que de "t". Je serais vraiment reconnaissant de toute aide.

OriginalL'auteur Mihai H | 2014-06-22