feat: 完善 New 方法支持指针和值参数,新增 interface 类型支持
- 支持指针模式: New(&data) - 直接修改原始数据
- 支持值模式: New(data) - 创建深度克隆,不影响原始数据
- 新增 interface{} 类型支持,自动解析到实际类型
- 对 map 和 slice 等引用类型也进行完全深度克隆
- 新增 9 个单元测试覆盖指针/值/interface 场景
- 新增 9 个示例测试展示各种用法
- 所有测试通过,保持性能
- 更新 README.md 详细说明指针/值传递的区别
- 新增 interface 类型使用示例
- 新增泛型数据处理使用场景
- 更新注意事项说明
- 使用递归解引用处理 interface 和指针类型
- 利用 DeepClone 确保引用类型的完全独立
- 保持向后兼容,现有代码无需修改
This commit is contained in:
124
README.md
124
README.md
@@ -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,请确保路径和类型正确
|
||||
|
||||
## 示例代码
|
||||
|
||||
|
||||
Reference in New Issue
Block a user