Heim > Backend-Entwicklung > Golang > So extrahieren Sie Typparameter mithilfe von Reflektion

So extrahieren Sie Typparameter mithilfe von Reflektion

王林
Freigeben: 2024-02-12 17:24:05
nach vorne
602 Leute haben es durchsucht

So extrahieren Sie Typparameter mithilfe von Reflektion

Frageninhalt

Kontext: Ich schreibe einen generischen Automapper, der zwei Arten von Strukturen akzeptiert, prüft, ob jedes Feld dieser Struktur eine bestimmte Bezeichnung hat, und dann die Werte von der Quellstruktur in Zielstrukturen kopiert , vorausgesetzt, sie haben passende Tags und Typen. Immer wenn ein Strukturfeld eine andere (verschachtelte) Struktur ist, möchte ich, dass die Automapper-Funktion einen rekursiven Aufruf ausführt, der das Kaninchenloch automatisch abbildet.

Problem: Ich kann nur den konkreten Typ der Wurzelstruktur übergeben. Sobald ich mit der Reflektion in die generische Funktion einsteige, scheint es unmöglich, den verschachtelten Strukturtyp zu extrahieren. Obwohl ich value.interface() als Parameter übergeben kann, muss ich dennoch den Typparameter übergeben.

Hier ist ein vereinfachter Code, um das Problem zu veranschaulichen.

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

Lösung

Dem Rat von @mkopriva folgend, wollte ich eine einfache Lösung für das Problem, das ich hatte, teilen.

Fühlen Sie sich frei, es zu korrigieren oder zu verbessern, aber denken Sie daran, dass ich unten absichtlich verschiedene Überprüfungen und Behauptungen nicht aufgeführt habe.

(Beispiel zum Spielplatz gehen)

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

Das obige ist der detaillierte Inhalt vonSo extrahieren Sie Typparameter mithilfe von Reflektion. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
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