struct_copy.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright 2019 getensh.com. All rights reserved.
  2. // Use of this source code is governed by getensh.com.
  3. package util
  4. import (
  5. "errors"
  6. "reflect"
  7. )
  8. func DeepFields(ifaceType reflect.Type) []reflect.StructField {
  9. var fields []reflect.StructField
  10. for i := 0; i < ifaceType.NumField(); i++ {
  11. v := ifaceType.Field(i)
  12. fields = append(fields, v)
  13. }
  14. return fields
  15. }
  16. // 拷贝结构体(将SrcStructPtr 拷贝到 DstStructPtr)
  17. // DstStructPtr 目标
  18. // SrcStructPtr 来源
  19. func StructCopy(DstStructPtr interface{}, SrcStructPtr interface{}) error {
  20. srcv := reflect.ValueOf(SrcStructPtr)
  21. dstv := reflect.ValueOf(DstStructPtr)
  22. srct := reflect.TypeOf(SrcStructPtr)
  23. dstt := reflect.TypeOf(DstStructPtr)
  24. if srct.Kind() != reflect.Ptr || dstt.Kind() != reflect.Ptr ||
  25. srct.Elem().Kind() == reflect.Ptr || dstt.Elem().Kind() == reflect.Ptr {
  26. return errors.New("Fatal error:type of parameters must be Ptr of value")
  27. }
  28. if srcv.IsNil() || dstv.IsNil() {
  29. return errors.New("Fatal error:value of parameters should not be nil")
  30. }
  31. srcV := srcv.Elem()
  32. dstV := dstv.Elem()
  33. srcfields := DeepFields(reflect.ValueOf(SrcStructPtr).Elem().Type())
  34. for _, v := range srcfields {
  35. if v.Anonymous {
  36. continue
  37. }
  38. if v.Type.Kind() == reflect.Struct || v.Type.Kind() == reflect.Slice {
  39. continue
  40. }
  41. dst := dstV.FieldByName(v.Name)
  42. src := srcV.FieldByName(v.Name)
  43. if !dst.IsValid() {
  44. continue
  45. }
  46. if src.Type() == dst.Type() && dst.CanSet() {
  47. dst.Set(src)
  48. continue
  49. }
  50. if src.Kind() == reflect.Ptr && !src.IsNil() && src.Type().Elem() == dst.Type() {
  51. dst.Set(src.Elem())
  52. continue
  53. }
  54. if dst.Kind() == reflect.Ptr && dst.Type().Elem() == src.Type() {
  55. dst.Set(reflect.New(src.Type()))
  56. dst.Elem().Set(src)
  57. continue
  58. }
  59. }
  60. return nil
  61. }