这个任务很简单。我有一个用于模型Foo的结构,还有一个用于它的表示的结构。
type Foo struct {
FooId string
Bar string
Baz *string
Salt int64
}
type FooView struct {
FooId *string `json: "foo_id"`
Bar *string `json: "bar"`
Baz *string `json: "baz"`
}
正如你所看到的, 我想隐藏Salt字段, 更改JSON字段名, 并做所有字段的选择. 目标方法应该像这样使用Foo来填充FooView。
func MirrorFoo(foo Foo) (*FooView, error) {
return &FooView{
FooId: &foo.FooId,
Bar: &foo.Bar,
Baz: foo.Baz,
}, nil
}
而现在,我想用Go反射来做同样的事情。
func Mirror(src interface{}, dstType reflect.Type) (interface{}, error) {
zeroValue := reflect.Value{}
srcValue := reflect.ValueOf(src)
srcType := srcValue.Type()
dstValue := reflect.New(dstType)
dstValueElem := dstValue.Elem()
for i := 0; i < srcType.NumField(); i++ {
srcTypeField := srcType.Field(i)
srcValueField := srcValue.FieldByName(srcTypeField.Name)
dstField := dstValueElem.FieldByName(srcTypeField.Name)
// if current source field exists in destination type
if dstField != zeroValue {
srcValueField := srcValue.Field(i)
if dstField.Kind() == reflect.Ptr && srcValueField.Kind() != reflect.Ptr {
panic("???")
} else {
dstField.Set(srcValueField)
}
}
}
return dstValue.Interface(), nil
}
当FooId是uuid.UUID时,这段代码可以正常工作,但当源是uuid.UUID而目标是*uuid.UUID时,它就失败了,现在不知道如何克服这个问题。
我需要用dstField.Set(reflect.ValueOf(&uuid.UUID{}...))做类比,不知怎么做,我试过的所有方法都没有用。有什么好办法吗?
是的,Addr()对我来说是可行的,但没有使用
reflect.Copy()
是针对数组的。我已经用reflect.New()和.Set()当前值实例化了新的值。地址变得可用。这完全是黑魔法。谢谢大家。