Maison > développement back-end > Golang > le corps du texte

Comment récupérer l'adresse de valeur des champs sans pointeur à l'aide de Reflection in Go ?

DDD
Libérer: 2024-10-29 19:35:02
original
759 Les gens l'ont consulté

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

Récupération de l'adresse de valeur à l'aide de la réflexion

Réfléchir sur une interface permet de parcourir ses champs. Cependant, obtenir l’adresse d’un champ non pointeur présente un défi. Cet article aborde ce problème en examinant les limites du déréférencement de pointeur et présente une solution.

Aperçu du problème

Considérez le 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>
Copier après la connexion

La fonction InspectStruct parcourt récursivement une structure et répertorie les détails de ses champs, y compris l'adresse. Voici une implémentation simplifiée :

<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>
Copier après la connexion

L'exécution de cette fonction sur une instance de type T donne :

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
Copier après la connexion

Comme vous pouvez le constater, les adresses des champs non pointeurs ("Id" et "F" de type "Z" et "V") ne sont pas accessibles.

Solution

Le problème vient du déréférencement de la valeur obtenue à partir de valueField.Interface( ). Cela renvoie une interface{} qui, lorsqu'elle est utilisée dans une valeur de champ, peut entraîner la perte des informations d'adresse.

Voici une solution modifiée qui résout ce problème :

<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>
Copier après la connexion

En passant un reflet .Value au lieu d'une interface{} vers InspectStructV, l'adresse du champ peut être obtenue correctement.

Conclusion

Lors du parcours de champs non pointeurs dans une structure en utilisant réflexion, il est crucial de préserver la réflexion.Value au lieu de s'appuyer sur valueField.Interface(). En passant Reflect.Value à la fonction récursive InspectStructV, vous pouvez récupérer avec succès les adresses des champs à n'importe quelle profondeur de la structure.

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!