Obtenir un pointeur vers la valeur à l'aide de la réflexion
La réflexion joue un rôle crucial dans l'introspection et la gestion dynamique des données dans Go. Cependant, cela présente des défis lors du ciblage de champs sans pointeur pour la récupération d'adresses. Cet article se concentre sur la résolution de ce problème et propose une solution pour obtenir l'adresse des champs non pointeurs dans les structures imbriquées à l'aide de la réflexion.
Considérez l'exemple de code suivant :
<code class="go">type Z struct { Id int } type V struct { Id int F Z } type T struct { Id int F V }</code>
Ici, T est une structure imbriquée avec F comme champ de type V, qui à son tour possède un autre champ F de type Z. Le but est de récupérer l'adresse du champ Id au sein de la structure Z.
En utilisant la réflexion, nous peut parcourir les champs et accéder à leurs valeurs. Cependant, le code ci-dessous montre comment gérer les champs sans pointeur et récupérer leurs adresses :
<code class="go">package main import ( "fmt" "reflect" ) func InspectStructV(val reflect.Value) { // Handle interface types if val.Kind() == reflect.Interface && !val.IsNil() { elm := val.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { val = elm } } // Dereference pointers if val.Kind() == reflect.Ptr { val = val.Elem() } // Iterate over fields for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) typeField := val.Type().Field(i) address := "not-addressable" // Handle nested interfaces if valueField.Kind() == reflect.Interface && !valueField.IsNil() { elm := valueField.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { valueField = elm } } // Dereference embedded pointers if valueField.Kind() == reflect.Ptr { valueField = valueField.Elem() } // Retrieve address if possible if valueField.CanAddr() { address = fmt.Sprintf("0x%X", valueField.Addr().Pointer()) } // Print field details 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()) // Recurse for nested structures if valueField.Kind() == reflect.Struct { InspectStructV(valueField) } } } func InspectStruct(v interface{}) { InspectStructV(reflect.ValueOf(v)) } func main() { 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) }</code>
En passant réflexion.Value directement au lieu de interface{} et en déréférençant les pointeurs imbriqués, ce code garantit que l'adresse de le champ Id dans la structure Z imbriquée peut être récupéré.
L'exemple de sortie ci-dessous démontre la récupération réussie de l'adresse du champ Id malgré sa profondeur dans la structure imbriquée :
Field Name: Id, Field Value: 1, Address: 0x40c1080088, Field type: int, Field kind: int Field Name: F, Field Value: {2 {3}}, Address: 0x40c108008c, Field type: main.V, Field kind: struct Field Name: Id, Field Value: 2, Address: 0x40c1080090, Field type: int, Field kind: int Field Name: F, Field Value: {3}, Address: 0x40c1080098, Field type: main.Z, Field kind: struct Field Name: Id, Field Value: 3, Address: 0x40c10800a0, Field type: int, Field kind: int
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!