package reflux import ( "reflect" "strings" "unicode" ) // DeepClone 深度克隆一个 reflect.Value func DeepClone(v reflect.Value) reflect.Value { // 解引用指针和接口以获取实际值 for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { if v.IsNil() { return reflect.Value{} } v = v.Elem() } if !v.IsValid() { return reflect.Value{} } // 创建新值的指针以便修改 cloned := reflect.New(v.Type()) CloneValue(cloned.Elem(), v) return cloned } // CloneValue 递归克隆值 func CloneValue(dst, src reflect.Value) { if !src.IsValid() { return } switch src.Kind() { case reflect.Ptr: if src.IsNil() { return } dst.Set(reflect.New(src.Type().Elem())) CloneValue(dst.Elem(), src.Elem()) case reflect.Interface: if src.IsNil() { return } cloned := DeepClone(src.Elem()) if cloned.IsValid() { dst.Set(cloned) } case reflect.Struct: for i := 0; i < src.NumField(); i++ { if dst.Field(i).CanSet() { CloneValue(dst.Field(i), src.Field(i)) } } case reflect.Slice: if src.IsNil() { return } dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) for i := 0; i < src.Len(); i++ { CloneValue(dst.Index(i), src.Index(i)) } case reflect.Array: for i := 0; i < src.Len(); i++ { CloneValue(dst.Index(i), src.Index(i)) } case reflect.Map: if src.IsNil() { return } dst.Set(reflect.MakeMap(src.Type())) for _, key := range src.MapKeys() { val := src.MapIndex(key) // Map 的值需要特殊处理 newVal := reflect.New(val.Type()).Elem() CloneValue(newVal, val) dst.SetMapIndex(key, newVal) } default: // 对于基本类型(int, string, bool, float等),直接赋值 if dst.CanSet() { dst.Set(src) } } } // expandPath 展开路径,支持点号分割 // 例如: expandPath("a.b", "c") -> []string{"a", "b", "c"} func expandPath(p ...string) []string { var result []string for _, segment := range p { // 按点号分割 parts := strings.Split(segment, ".") for _, part := range parts { if part != "" { // 忽略空字符串 result = append(result, part) } } } return result } // capitalizeFirst 将字符串首字母转换为大写 // 用于处理 struct 字段名,使其符合 Go 的公开字段命名规范 func capitalizeFirst(s string) string { if s == "" { return s } runes := []rune(s) runes[0] = unicode.ToUpper(runes[0]) return string(runes) } // tryStructField 尝试获取 struct 字段,支持小写字段名自动转大写 // 1. 首先尝试原始字段名 // 2. 如果失败且首字母是小写,尝试首字母大写的版本 func tryStructField(v reflect.Value, fieldName string) reflect.Value { // 首先尝试原始字段名 field := v.FieldByName(fieldName) if field.IsValid() { return field } // 如果字段名首字母是小写,尝试首字母大写 if len(fieldName) > 0 && unicode.IsLower(rune(fieldName[0])) { capitalizedName := capitalizeFirst(fieldName) field = v.FieldByName(capitalizedName) if field.IsValid() { return field } } return reflect.Value{} }