copy_struct.go 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package sessdata
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. // 用b的所有字段覆盖a的
  7. // 如果fields不为空, 表示用b的特定字段覆盖a的
  8. // a应该为结构体指针
  9. func CopyStruct(a interface{}, b interface{}, fields ...string) (err error) {
  10. at := reflect.TypeOf(a)
  11. av := reflect.ValueOf(a)
  12. bt := reflect.TypeOf(b)
  13. bv := reflect.ValueOf(b)
  14. // 简单判断下
  15. if at.Kind() != reflect.Ptr {
  16. err = fmt.Errorf("a must be a struct pointer")
  17. return
  18. }
  19. av = reflect.ValueOf(av.Interface())
  20. // 要复制哪些字段
  21. _fields := make([]string, 0)
  22. if len(fields) > 0 {
  23. _fields = fields
  24. } else {
  25. for i := 0; i < bv.NumField(); i++ {
  26. _fields = append(_fields, bt.Field(i).Name)
  27. }
  28. }
  29. if len(_fields) == 0 {
  30. fmt.Println("no fields to copy")
  31. return
  32. }
  33. // 复制
  34. for i := 0; i < len(_fields); i++ {
  35. name := _fields[i]
  36. f := av.Elem().FieldByName(name)
  37. bValue := bv.FieldByName(name)
  38. // a中有同名的字段并且类型一致才复制
  39. if f.IsValid() && f.Kind() == bValue.Kind() {
  40. f.Set(bValue)
  41. }
  42. }
  43. return
  44. }