Files
copier/reflect.go
T
charlie a6990aa4af refactor: split copier.go into smaller files
Split monolithic copier.go (1077 lines) into focused modules:
- copier.go: Core framework (95 lines)
- copy_value.go: Copy functions and type handling (858 lines)
- reflect.go: Reflection utilities (100 lines)
- converter.go: Type converter (38 lines)
- options.go: Configuration (renamed from optiongs.go)

Bug fixes:
- Fixed string to *string copying (empty strings now work)
- Fixed *time.Time to *time.Time copying
- Fixed nil slice handling
- Fixed copyStructToSlice pointer element handling

Tests: Fixed critical data copy issues. Remaining method-mapping
features require additional implementation.
2026-04-24 01:11:22 +08:00

101 lines
2.1 KiB
Go

package copier
import (
"reflect"
"strings"
)
func nestedAnonymousField(dst reflect.Value, fieldName string) bool {
if f, ok := dst.Type().FieldByName(fieldName); ok {
if len(f.Index) > 1 {
destField := dst.Field(f.Index[0])
if destField.Kind() != reflect.Pointer {
return false
}
if !destField.IsNil() {
return false
}
if destField.CanSet() {
destField.Set(reflect.New(destField.Type().Elem()))
} else {
return true
}
}
}
return false
}
func (c *copier) getFieldName(name string, tag *tagOption) string {
if tag != nil && tag.Contains(tagName) {
return tag.name
}
return c.opt.NameConvert(name)
}
func (c *copier) getFieldName2(fieldName string, tag *tagOption) (srcFieldName string, dstFieldName string) {
return fieldName, c.getFieldName(fieldName, tag)
}
func (c *copier) fieldByName(v reflect.Value, name string) reflect.Value {
if c.opt != nil && c.opt.caseSensitive {
return v.FieldByName(name)
}
return v.FieldByNameFunc(func(s string) bool { return strings.EqualFold(s, name) })
}
func (c *copier) ExceedMaxDepth(depth int) bool {
return c.opt.maxDepth > 0 && depth >= c.opt.maxDepth
}
func (c *copier) isCircularRefs(v reflect.Value) bool {
if !c.opt.detectCircularRefs || !v.IsValid() || !v.CanAddr() {
return false
}
ptr := c.getValuePointer(v)
if _, exists := c.visited[ptr]; exists {
return true
}
c.visited[ptr] = struct{}{}
return false
}
func (c *copier) getValuePointer(v reflect.Value) uintptr {
switch v.Kind() {
case reflect.Pointer, reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
return v.Pointer()
case reflect.Struct:
if v.CanAddr() {
return v.Addr().Pointer()
}
}
return 0
}
func indirect(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface {
if v.IsNil() {
break
}
v = v.Elem()
}
return v
}
func indirectType(reflectType reflect.Type) (_ reflect.Type, isPtr bool) {
for reflectType.Kind() == reflect.Pointer || reflectType.Kind() == reflect.Slice {
reflectType = reflectType.Elem()
isPtr = true
}
return reflectType, isPtr
}