Heim >Backend-Entwicklung >Golang >Wie rufe ich die Wertadresse von Nicht-Zeigerfeldern mithilfe von Reflection in Go ab?
Wertadresse mithilfe von Reflexion abrufen
Die Reflexion über eine Schnittstelle ermöglicht es einem, deren Felder zu durchqueren. Allerdings stellt das Ermitteln der Adresse eines Nicht-Zeigerfelds eine Herausforderung dar. Dieser Artikel befasst sich mit diesem Problem, indem er die Einschränkungen der Zeiger-Dereferenzierung untersucht und eine Lösung vorstellt.
Problemübersicht
Bedenken Sie den folgenden Code:
<code class="go">type Z struct { Id int } type V struct { Id int F Z } type T struct { Id int F V }</code>
Die Funktion InspectStruct durchläuft rekursiv eine Struktur und listet ihre Felddetails, einschließlich der Adresse, auf. Hier ist eine vereinfachte Implementierung:
<code class="go">func InspectStruct(o interface{}) { val := reflect.ValueOf(o) if val.Kind() == reflect.Interface && !val.IsNil() { val = val.Elem() } if val.Kind() == reflect.Ptr { val = val.Elem() } for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) if valueField.Kind() == reflect.Ptr { valueField = valueField.Elem() } address := "not-addressable" if valueField.CanAddr() { address = fmt.Sprint(valueField.Addr().Pointer()) } fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\n", val.Type().Field(i).Name, valueField.Interface(), address) if valueField.Kind() == reflect.Struct { InspectStruct(valueField.Interface()) } } }</code>
Das Ausführen dieser Funktion auf einer Instanz vom Typ T ergibt:
Field Name: Id, Field Value: 1, Address: 408125440 Field Name: F, Field Value: {2 {3}}, Address: 408125444 Field Name: Id, Field Value: 2, Address: not-addressable Field Name: F, Field Value: {3}, Address: not-addressable Field Name: Id, Field Value: 3, Address: not-addressable
Wie Sie sehen können, sind die Adressen von Nicht-Zeigerfeldern („Id“) und „F“ vom Typ „Z“ und „V“) sind nicht zugänglich.
Lösung
Das Problem ergibt sich aus der Dereferenzierung des von valueField.Interface( ). Dies gibt eine Schnittstelle{} zurück, die bei Verwendung in einem Feldwert zum Verlust der Adressinformationen führen kann.
Hier ist eine modifizierte Lösung, die dieses Problem behebt:
<code class="go">func InspectStructV(val reflect.Value) { if val.Kind() == reflect.Interface && !val.IsNil() { val = val.Elem() } if val.Kind() == reflect.Ptr { val = val.Elem() } for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) if valueField.Kind() == reflect.Ptr { valueField = valueField.Elem() } address := "not-addressable" if valueField.CanAddr() { address = fmt.Sprintf("0x%X", valueField.Addr().Pointer()) } fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\n", val.Type().Field(i).Name, valueField.Interface(), address) if valueField.Kind() == reflect.Struct { InspectStructV(valueField) } } } func InspectStruct(v interface{}) { InspectStructV(reflect.ValueOf(v)) }</code>
Durch Übergabe eines Reflekts .Value anstelle einer Schnittstelle{} zu InspectStructV, die Adresse des Feldes kann korrekt abgerufen werden.
Schlussfolgerung
Beim Durchlaufen von Nicht-Zeigerfeldern in einer Struktur mit Bei der Reflexion ist es wichtig, den „reflect.Value“ beizubehalten, anstatt sich auf „valueField.Interface()“ zu verlassen. Durch die Übergabe von „reflect.Value“ an die rekursive InspectStructV-Funktion können Sie die Adressen von Feldern in jeder Tiefe der Struktur erfolgreich abrufen.
Das obige ist der detaillierte Inhalt vonWie rufe ich die Wertadresse von Nicht-Zeigerfeldern mithilfe von Reflection in Go ab?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!