上下文:我正在编写一个通用自动映射器,它采用两种类型的结构,检查所述结构的每个字段是否有给定的标签,然后将值从源结构复制到目标结构,假设它们具有匹配的标签和类型。每当结构字段是另一个(嵌套)结构时,我希望自动映射器函数执行递归调用,自动映射到兔子洞。
问题:我只能传递根结构的具体类型。一旦我进入使用反射的通用函数,尝试提取嵌套的结构类型似乎是不可能的。 虽然我可以传递 value.interface() 作为参数,但我仍然需要传递类型参数。
这里有一些简化的代码来显示问题。
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 }
按照@mkopriva的建议,我想分享一个简单的解决方案来解决我遇到的问题。 p>
请随意纠正或改进它,但请记住,我故意不包括下面的各种检查和断言。
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 }
以上是如何使用反射提取类型参数的详细内容。更多信息请关注PHP中文网其他相关文章!