feat: 完善 New 方法支持指针和值参数,新增 interface 类型支持

- 支持指针模式: New(&data) - 直接修改原始数据
- 支持值模式: New(data) - 创建深度克隆,不影响原始数据
- 新增 interface{} 类型支持,自动解析到实际类型
- 对 map 和 slice 等引用类型也进行完全深度克隆

- 新增 9 个单元测试覆盖指针/值/interface 场景
- 新增 9 个示例测试展示各种用法
- 所有测试通过,保持性能

- 更新 README.md 详细说明指针/值传递的区别
- 新增 interface 类型使用示例
- 新增泛型数据处理使用场景
- 更新注意事项说明

- 使用递归解引用处理 interface 和指针类型
- 利用 DeepClone 确保引用类型的完全独立
- 保持向后兼容,现有代码无需修改
This commit is contained in:
2025-12-02 21:08:13 +08:00
parent d9f178020a
commit 97d41fa6d8
4 changed files with 520 additions and 24 deletions

124
README.md
View File

@@ -9,7 +9,9 @@ Reflux 是一个 Go 语言包,提供了统一的接口用于访问和操作嵌
- 🔄 **类型转换**: 基于 [spf13/cast](https://github.com/spf13/cast) 的强大类型转换支持
- ✏️ **修改数据**: 支持通过路径设置和删除值
- 🔗 **链式调用**: Set 和 Delete 方法支持链式调用,如 `rfx.Set("name", "Alice").Delete("age").Set("city", "Beijing")`
- 📋 **深度克隆**: Scope 方法创建深度克隆,修改不影响原始数据
- 📋 **深度克隆**: Scope 方法和值传递模式创建深度克隆,修改不影响原始数据
- 🎭 **灵活模式**: 支持指针和值两种传递方式,提供不同的数据操作语义
- 🔌 **Interface 支持**: 自动解析 `interface{}` 类型到实际类型
- 🔤 **大小写不敏感**: 支持使用小写字段名访问和修改结构体字段
- 🔑 **键名提取**: Keys 方法可获取结构体或 Map 的所有键名
- 📝 **JSON 集成**: Ptr() 方法返回的指针可直接用于 json.Unmarshal(),实现动态 JSON 反序列化
@@ -68,12 +70,62 @@ func main() {
### 1. 创建 Reflux
Reflux 支持**指针**和**值**两种传递方式,提供不同的数据操作语义:
#### 指针模式 - 直接修改原始数据
```go
user := User{Name: "Alice"}
rfx := reflux.New(&user) // 传入指针以支持修改
rfx := reflux.New(&user) // 传入指针
rfx.Set("Name", "Bob")
// user.Name 已被修改为 "Bob"
```
**重要**: `New()` 函数必须传入指针类型,否则会 panic。
#### 值模式 - 深度克隆,不影响原始数据
```go
user := User{Name: "Alice"}
rfx := reflux.New(user) // 传入值
rfx.Set("Name", "Bob")
// user.Name 仍然是 "Alice"
// rfx 内部是独立的深度克隆
```
#### Interface 类型支持
Reflux 支持 `interface{}` (或 `any`) 类型,会自动解析到实际类型:
```go
// interface{} 包装的值 - 创建深度克隆
var config any = map[string]string{"host": "localhost"}
rfx := reflux.New(config)
rfx.Set("host", "127.0.0.1")
// 原始 config 不受影响
// interface{} 包装的指针 - 直接修改
var data any = &config
rfx := reflux.New(data)
rfx.Set("host", "127.0.0.1")
// config 已被修改
```
#### 支持的类型
| 类型 | 说明 | 示例 |
|-----|------|------|
| **Struct** | 结构体 | `New(Person{})``New(&person)` |
| **Map** | 映射 | `New(map[string]any{})``New(&m)` |
| **Slice** | 切片 | `New([]string{})``New(&s)` |
| **Array** | 数组 | `New([3]int{})``New(&a)` |
| **Interface** | 接口 | `New(anyValue)` - 自动解析 |
**重要说明**:
-**指针模式**: 传入指针(如 `&user`)时,所有修改都会**直接影响原始数据**
-**值模式**: 传入值(如 `user`)时,会创建**深度克隆**,修改不影响原始数据
-**深度克隆**: 对于 map 和 slice 等引用类型,值模式也会创建完全独立的副本
-**不支持**: 基本类型(int, string, bool)、chan、func 等不是容器的类型
### 2. 获取值 (Get)
@@ -581,6 +633,48 @@ func main() {
- **插件热加载**: 更新插件配置而无需重启
- **API 部分响应**: 只处理 API 返回的部分字段
### 7. 泛型数据处理 (Interface 类型)
使用 interface{} 类型处理未知类型的数据:
```go
// 函数返回 any 类型
func loadFromAPI() any {
// 可能返回 map 或 struct
return map[string]any{
"user": map[string]any{
"name": "Alice",
"age": 30,
},
}
}
func processData(data any) {
// 自动解析 interface{} 到实际类型
rfx := reflux.New(data) // 值模式,创建深度克隆
// 安全地修改数据
rfx.Set("user.name", "Bob")
rfx.Set("user.age", 35)
// 原始数据不受影响
}
// 或者使用指针模式
func updateData(dataPtr any) {
// interface{} 包装指针,直接修改
rfx := reflux.New(dataPtr)
rfx.Set("user.name", "Charlie")
// 原始数据已被修改
}
```
使用场景:
- **插件系统**: 处理未知结构的插件配置
- **泛型配置**: 统一处理不同格式的配置数据
- **API 适配**: 适配多种 API 响应格式
- **数据转换**: 在不同数据结构间转换
## 路径语法
Reflux 支持灵活的点号路径语法:
@@ -667,16 +761,20 @@ type Reflux interface {
## 注意事项
1. **指针传递**: `New()` 函数必须传递指针,否则会 panic
2. **Scope 行为**: `Scope` 返回深度克隆,修改会影响原始数据
3. **链式调用**: Set 和 Delete 方法都支持链式调用,返回 Reflux 自身
4. **类型转换**: 使用 spf13/cast 进行类型转换,转换失败会 panic
5. **切片删除**: 删除切片元素会创建新切片并重新赋值
6. **Map 初始化**: 对 nil map 调用 Set 会自动初始化 map
7. **大小写不敏感**: 支持使用小写字段名访问结构体字段
8. **JSON 集成**: Ptr() 返回的指针可以安全地用于 json.Unmarshal()
9. **并发安全**: Reflux 本身不是并发安全的,需要外部同步
10. **错误处理**: 大多数转换、设置和删除操作失败时会 panic,请确保路径和类型正确
1. **指针 vs 值传递**:
- 传入**指针** (`New(&data)`) 时,修改会影响原始数据
- 传入**值** (`New(data)`) 时,会创建深度克隆,修改不影响原始数据
- 对于 map 和 slice 等引用类型,值模式也会完全克隆
2. **Interface 支持**: 支持 `interface{}` 类型,会自动解析到实际类型并保持正确的指针/值语义
3. **Scope 行为**: `Scope` 返回深度克隆,修改不会影响原始数据
4. **链式调用**: Set 和 Delete 方法都支持链式调用,返回 Reflux 自身
5. **类型转换**: 使用 spf13/cast 进行类型转换,转换失败会 panic
6. **切片删除**: 删除切片元素会创建新切片并重新赋值
7. **Map 初始化**: 对 nil map 调用 Set 会自动初始化 map
8. **大小写不敏感**: 支持使用小写字段名访问结构体字段
9. **JSON 集成**: Ptr() 返回的指针可以安全地用于 json.Unmarshal()
10. **并发安全**: Reflux 本身不是并发安全的,需要外部同步
11. **错误处理**: 大多数转换、设置和删除操作失败时会 panic,请确保路径和类型正确
## 示例代码