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

View File

@@ -23,15 +23,155 @@ type Address struct {
// TestNew 测试 New 函数
func TestNew(t *testing.T) {
p := Person{Name: "Alice", Age: 30}
t.Run("New with pointer", func(t *testing.T) {
// 测试传入指针 - 修改应该影响原始数据
p := Person{Name: "Alice", Age: 30}
rfx := New(&p)
// 测试传入非指针值应该 panic
defer func() {
if r := recover(); r == nil {
t.Error("New() with non-pointer should panic")
rfx.Set("Name", "Bob")
if p.Name != "Bob" {
t.Errorf("Expected original value to be modified, got '%s'", p.Name)
}
}()
New(p) // 应该 panic
})
t.Run("New with value", func(t *testing.T) {
// 测试传入值 - 修改不应该影响原始数据
p := Person{Name: "Alice", Age: 30}
rfx := New(p)
rfx.Set("Name", "Bob")
// 原始值不应该被修改
if p.Name != "Alice" {
t.Errorf("Expected original value to remain 'Alice', got '%s'", p.Name)
}
// rfx 内部的值应该已经修改
if rfx.Get("Name").String() != "Bob" {
t.Errorf("Expected rfx value to be 'Bob', got '%s'", rfx.Get("Name").String())
}
})
t.Run("New with map pointer", func(t *testing.T) {
m := map[string]any{"name": "Alice"}
rfx := New(&m)
rfx.Set("name", "Bob")
if m["name"] != "Bob" {
t.Errorf("Expected map to be modified, got '%v'", m["name"])
}
})
t.Run("New with map value", func(t *testing.T) {
m := map[string]any{"name": "Alice"}
rfx := New(m)
rfx.Set("name", "Bob")
// 原始 map 不应该被修改
if m["name"] != "Alice" {
t.Errorf("Expected original map to remain 'Alice', got '%v'", m["name"])
}
})
t.Run("New with slice pointer", func(t *testing.T) {
s := []string{"a", "b", "c"}
rfx := New(&s)
rfx.Set("0", "x")
if s[0] != "x" {
t.Errorf("Expected slice to be modified, got '%s'", s[0])
}
})
t.Run("New with slice value", func(t *testing.T) {
s := []string{"a", "b", "c"}
rfx := New(s)
rfx.Set("0", "x")
// 原始切片不应该被修改
if s[0] != "a" {
t.Errorf("Expected original slice to remain 'a', got '%s'", s[0])
}
})
t.Run("New with array value", func(t *testing.T) {
a := [3]string{"a", "b", "c"}
rfx := New(a)
rfx.Set("0", "x")
// 原始数组不应该被修改
if a[0] != "a" {
t.Errorf("Expected original array to remain 'a', got '%s'", a[0])
}
})
t.Run("New with nil pointer", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic with nil pointer")
}
}()
var p *Person
New(p)
})
t.Run("New with unsupported type", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic with unsupported type")
}
}()
New(42) // int 不支持
})
t.Run("New with interface wrapping map", func(t *testing.T) {
// 测试 interface{} 包装的 map
var data any = map[string]string{"name": "Alice"}
rfx := New(data)
if rfx.Get("name").String() != "Alice" {
t.Errorf("Expected 'Alice', got '%s'", rfx.Get("name").String())
}
// 修改不应该影响原始数据(因为是值传递)
rfx.Set("name", "Bob")
originalMap := data.(map[string]string)
if originalMap["name"] != "Alice" {
t.Error("Original map should not be modified")
}
})
t.Run("New with interface wrapping struct", func(t *testing.T) {
// 测试 interface{} 包装的 struct
var data any = Person{Name: "Alice", Age: 30}
rfx := New(data)
if rfx.Get("Name").String() != "Alice" {
t.Errorf("Expected 'Alice', got '%s'", rfx.Get("Name").String())
}
})
t.Run("New with interface wrapping pointer", func(t *testing.T) {
// 测试 interface{} 包装的指针
person := Person{Name: "Alice", Age: 30}
var data any = &person
rfx := New(data)
rfx.Set("Name", "Bob")
// 原始数据应该被修改(因为是指针)
if person.Name != "Bob" {
t.Errorf("Expected original to be modified, got '%s'", person.Name)
}
})
t.Run("New with nil interface", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic with nil interface")
}
}()
var data any
New(data)
})
}
// TestNewWithPointer 测试传入指针的情况