Maison > développement back-end > Golang > Comment extraire les paramètres de type à l'aide de la réflexion

Comment extraire les paramètres de type à l'aide de la réflexion

王林
Libérer: 2024-02-12 17:24:05
avant
620 Les gens l'ont consulté

Comment extraire les paramètres de type à laide de la réflexion

Contenu de la question

Contexte : j'écris un automapper générique qui prend deux types de structures, vérifie si chaque champ de ladite structure a une étiquette donnée, puis copie les valeurs de la structure source vers les structures cibles , en supposant qu'ils ont des balises et des types correspondants. Chaque fois qu'un champ de structure est une autre structure (imbriquée), je souhaite que la fonction automapper effectue un appel récursif qui cartographie automatiquement le terrier du lapin.

Problème : je ne peux transmettre que le type concret de la structure racinaire. Une fois que j'entre dans la fonction générique en utilisant la réflexion, essayer d'extraire le type de structure imbriquée semble impossible. Bien que je puisse passer value.interface() comme paramètre, je dois quand même passer le paramètre type.

Voici un code simplifié pour montrer le problème.

type Alpha struct {
    Nested Beta `automap:"nested"`
}

type Beta struct {
    Info string `automap:"info"`
}

type Foo struct {
    Nested Bar `automap:"nested"`
}

type Bar struct {
    Info string `automap:"info"`
}

func TestAutoMap(t *testing.T) {

    b := Beta{Info: "Hello from Beta!"}
    a := Alpha{Nested: b}

    f, err := AutoMap[Alpha, Foo](a)
    if err != nil {
        fmt.Println(err)
        t.Fail()
    }
    fmt.Println("f.nested.info:", f.Nested.Info)
}

func AutoMap[S, T any](source S) (target T, err error) {

    targetStruct := reflect.ValueOf(&target).Elem()
    sourceStruct := reflect.ValueOf(&source).Elem()

    // .Type and .Kind directly did not work.
    nestedSourceType := ??? // I want this to be type Beta.
    nestedTargetType := ??? // I want this to be type Bar.

    sourceInterface := sourceStruct.Interface()

    t, err := AutoMap[nestedSourceType, nestedTargetType](sourceInterface)
    if err != nil {
        return target, err
    }
    target = t

    return target, nil
}
Copier après la connexion

Solution

Suite aux conseils de @mkopriva J'avais envie de partager une solution simple au problème que je rencontrais.

N'hésitez pas à le corriger ou à l'améliorer, mais gardez à l'esprit que je n'ai intentionnellement pas inclus diverses vérifications et affirmations ci-dessous.

(exemple de terrain de jeu Go)

type Alpha struct {
    NestedOnce Beta
}

type Beta struct {
    NestedTwice Gamma
}

type Gamma struct {
    Info string
}

type Foo struct {
    NestedOnce Bar
}

type Bar struct {
    NestedTwice Baz
}

type Baz struct {
    Info string
}

func TestAutoMap(t *testing.T) {

    g := Gamma{"Hello from Gamma!"}
    b := Beta{g}
    a := Alpha{b}

    f, err := AutoMap[Foo](a)
    if err != nil {
        fmt.Println(err)
        t.Fail()
    } else {
        fmt.Println("Foo.NestedOnce.NestedTwice.Info:", f.NestedOnce.NestedTwice.Info)
    }
}

func AutoMap[T any](source any) (target T, err error) {

    // Peel off 'any' from the function parameter type.
    sourceStruct := reflect.ValueOf(&source).Elem().Elem()

    targetStruct := reflect.ValueOf(&target).Elem()

    err = autoMap(sourceStruct, targetStruct)

    return target, err
}

func autoMap(s, t reflect.Value) error {

    sourceField := s.Field(0)
    targetField := t.Field(0)

    if sourceField.Kind() == reflect.Struct {
        err := autoMap(sourceField, targetField)
        if err != nil {
            return err
        }
        return nil
    }

    targetField.Set(sourceField)

    return nil
}
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
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