Heim > Backend-Entwicklung > Golang > Wie rufe ich die Wertadresse von Nicht-Zeigerfeldern mithilfe von Reflection in Go ab?

Wie rufe ich die Wertadresse von Nicht-Zeigerfeldern mithilfe von Reflection in Go ab?

DDD
Freigeben: 2024-10-29 19:35:02
Original
833 Leute haben es durchsucht

How to Retrieve the Value Address of Non-Pointer Fields Using Reflection in Go?

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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
Nach dem Login kopieren

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>
Nach dem Login kopieren

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!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage