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 }
Suite aux conseils de @mkopriva J'avais envie de partager une solution simple au problème que je rencontrais. p>
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 }
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!