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
DDDOriginal
2024-10-29 19:35:02835Durchsuche

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>

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!

Stellungnahme:
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