实现方法
func StructCopy(DstStructPtr interface{}, SrcStructPtr interface{}) {
a := reflect.ValueOf(SrcStructPtr)
b := reflect.ValueOf(DstStructPtr)
aT := reflect.TypeOf(SrcStructPtr)
bT := reflect.TypeOf(DstStructPtr)
if aT.Kind() != reflect.Ptr || bT.Kind() != reflect.Ptr ||
aT.Elem().Kind() == reflect.Ptr || bT.Elem().Kind() == reflect.Ptr {
log.Error("warning:type of parameters must be Ptr of value")
return
}
if a.IsNil() || b.IsNil() {
log.Error("warning:value of parameters should not be nil")
return
}
srcV := a.Elem()
dstV := b.Elem()
srcFields := DeepFields(reflect.ValueOf(SrcStructPtr).Elem().Type())
for _, v := range srcFields {
if v.Anonymous {
continue
}
dst := dstV.FieldByName(v.Name)
src := srcV.FieldByName(v.Name)
if !dst.IsValid() {
continue
}
if src.Type() == dst.Type() && dst.CanSet() {
dst.Set(src)
continue
}
if src.Kind() == reflect.Ptr && !src.IsNil() && src.Type().Elem() == dst.Type() {
dst.Set(src.Elem())
continue
}
if dst.Kind() == reflect.Ptr && dst.Type().Elem() == src.Type() {
dst.Set(reflect.New(src.Type()))
dst.Elem().Set(src)
continue
}
}
return
}
func DeepFields(faceType reflect.Type) []reflect.StructField {
var fields []reflect.StructField
for i := 0; i < faceType.NumField(); i++ {
v := faceType.Field(i)
if v.Anonymous && v.Type.Kind() == reflect.Struct {
fields = append(fields, DeepFields(v.Type)...)
} else {
fields = append(fields, v)
}
}
return fields
}
测试方法
type DstStructTest struct {
Name string
}
type SrcStructTest struct {
Name string
}
func Test_StructCopy(t *testing.T) {
src := SrcStructTest{Name: "1"}
var dst DstStructTest
StructCopy(&dst, &src)
}