package util import ( "fmt" "reflect" ) func CopyStructSameField(dst interface{}, src interface{}) error { d := reflect.ValueOf(dst) if d.Kind() != reflect.Ptr { return fmt.Errorf("dst is not ptr") } d = d.Elem() if d.Kind() != reflect.Struct { return fmt.Errorf("dst is not struct") } s := reflect.ValueOf(src) if s.Kind() == reflect.Ptr { s = s.Elem() } if s.Kind() != reflect.Struct { return fmt.Errorf("src is not struct") } srcmap := map[string]reflect.Value{} numField := s.NumField() for i := 0; i < numField; i++ { srcmap[s.Type().Field(i).Name] = s.Field(i) } numField = d.NumField() for i := 0; i < numField; i++ { name := d.Type().Field(i).Name if v, ok := srcmap[name]; ok { if v.Type().Kind() == d.Type().Field(i).Type.Kind() { if v.Type().Kind() == reflect.Struct { CopyStructSameField(d.Field(i).Addr().Interface(), v.Interface()) } else if v.Type().Kind() == reflect.Slice { d.Field(i).Set(reflect.MakeSlice(d.Field(i).Type(), 0, v.Len())) if t, err := CopySlice(d.Field(i).Interface(), v.Interface()); err == nil { tmp := reflect.ValueOf(t) d.Field(i).Set(reflect.MakeSlice(d.Field(i).Type(), tmp.Len(), tmp.Len())) reflect.Copy(d.Field(i), reflect.ValueOf(t)) } } else { d.Field(i).Set(v) } } } } return nil } func CopySlice(dst interface{}, src interface{}) (ddd interface{}, err error) { d := reflect.ValueOf(dst) if d.Kind() == reflect.Ptr { d = d.Elem() } if d.Kind() != reflect.Slice { return dst, fmt.Errorf("dst is not slice") } s := reflect.ValueOf(src) if s.Kind() == reflect.Ptr { s = s.Elem() } if s.Kind() != reflect.Slice { return dst, fmt.Errorf("src is not slice") } count := s.Len() for i := 0; i < count; i++ { t := reflect.New(d.Type().Elem()) if t.Type().Elem().Kind() == reflect.Struct && s.Index(i).Type().Kind() == reflect.Struct { CopyStructSameField(t.Interface(), s.Index(i).Interface()) } else if t.Kind() == reflect.Slice && s.Index(i).Kind() == reflect.Slice { CopySlice(t, s.Field(i)) } else if t.Kind() != reflect.Slice && t.Kind() != reflect.Struct && s.Index(i).Kind() != reflect.Slice && s.Index(i).Kind() != reflect.Struct { t.Set(s.Field(i)) } d = reflect.Append(d, t.Elem()) } return d.Interface(), nil }