what
|
05522809b9
|
docs: 修正 README 中会被渲染成删除线的波浪号
GFM 支持单波浪线删除线(~text~), 所以同一行出现两个 ~ 时,
'快 3~4 倍,访问器快 8~12 倍' 会把中间的 '4 倍,访问器快 8' 渲染成删除线。
表示数值范围的 ~ 统一改为 -。
|
2026-08-28 17:09:07 +08:00 |
|
what
|
659fc10bae
|
fix: 修正 Example 函数命名与输出注释位置,让 go vet / go test 恢复可用
go vet ./... 此前有 13 处失败, 导致 go test ./...(默认带 vet)根本跑不起来,
必须加 -vet=off。这是既存问题, 与实现改动无关。
命名问题(12 处): Example 函数名的前缀必须是包内真实存在的标识符。
ExampleStructMap_* -> ExampleR_* (包里没有 StructMap)
ExampleSet_* -> ExampleR_Set_* (Set 是 R 的方法, 不是包级函数)
ExampleAppend_* -> ExampleR_Append_* (同上)
ExampleSchema_Unmarshal -> ExampleSchema_unmarshalJSON
(Schema 没有 Unmarshal 方法,
这个例子演示的是 json.Unmarshal)
输出注释位置(1 处): ExampleR_Append_typeConversionError 的 // Output: 后面
还跟着一条注释, 违反"Output 必须是最后一个注释块"。因为格式不合法, Go 一直
没把它当输出例子比对 —— 里面写的期望输出其实是错的(与实际信息不符)也没被发现。
把注释挪到 defer 之前, 并把期望输出更正为真实的 panic 信息。
已验证: 故意改错期望输出现在会导致测试失败, 说明确实在比对了。
现在 go vet ./... 干净, go test ./... 无需 -vet=off 即可运行。
|
2026-08-28 17:02:56 +08:00 |
|
what
|
e594e206f0
|
test: 补上 addrOf 的测试覆盖
addrOf 是 unsafeptr.go 里唯一没有测试覆盖的函数。它的触发路径比较隐蔽:
interface 字段里装着一个 Accessor, 且它的 Raw() 返回**可寻址的非指针**值,
此时 fromReflect 才会走 CanAddr 分支。老实现 refx 的 Get 结果正是这种形态。
补测之后核心实现(rfx/typedesc/unsafeptr/path/generic)达到 100% 函数覆盖,
unsafe 代码逐个函数都有测试经过。
|
2026-08-28 16:56:08 +08:00 |
|
what
|
9cb3ea857e
|
fix: 补齐 Get[T] 的类型分支,避免静默返回零值
Get[T] 原本只处理 string/int/int64/bool/float64 五种,其余类型掉进 default
分支的 Any().(T) 断言。而断言**不做转换**,导致:
Get[int32](r, "Age") // 字段是 int(42) -> 静默返回 0
Get[[]string](r, "Tags") // 字段是 []any -> 静默返回 nil
Get[map[string]string](r, "M") // 字段是 map[string]any -> 静默返回 nil
而对应的访问器 r.Get("Age").Int32() 等返回的是正确的转换结果。
实测 8 个场景里 7 个静默给错数据 —— 不报错不 panic,是最难排查的一类问题。
补齐后 T 覆盖 valuex.Accessor 全部转换方法对应的类型(9 个标量 + 4 种切片
+ 6 种 map),每个分支都落到同名访问器上,转换语义完全一致。
五种快路径类型的零分配特性不受影响(新分支同样用 detachPath 切断逃逸)。
新增 TestGenericMirrorsAccessors: 23 个用例逐个比对 Get[T] 与同名访问器,
并额外断言结果不是零值,防止将来有人删掉分支又掉回 default。
|
2026-08-28 16:50:43 +08:00 |
|
what
|
a6283ac432
|
fix: 修正 fieldx 中过时的字段缺失测试并补齐 Required 覆盖
TestSchema_Generate_FieldNotFound 断言字段缺失时报错, 但用例里没有设置
Required: true。按 Field.Required 的文档语义, 只有 Required 为 true 时字段
缺失才算错误, 否则取到 nil 继续 —— 所以这个测试一直是失败状态, 应该是在
Required 引入之前写的, 加了 Required 之后没有同步更新。
修正: 给用例加上 Required: true, 让它真正测到报错分支。
另补 TestSchema_Generate_OptionalFieldNotFound 覆盖非必需分支 ——
Required 此前在整个包里没有任何测试覆盖。
|
2026-08-28 16:42:04 +08:00 |
|
what
|
5c9f8bd6e7
|
perf: 用类型布局缓存 + 指针偏移寻址重写热路径
将实验目录 experiment/fastx 的实现合入主实现,替换原来逐次反射的做法。
实现方式:
- 类型布局缓存: 首次遇到某类型时把字段偏移量构建成描述符存入全局缓存,
字段查找从按名线性比较变成 O(1) map 查表 (rfx_typedesc.go)
- 指针偏移寻址: 取字段时用 基址+偏移量 直接算地址, 不再构造中间 reflect.Value
(unsafeptr.go, 全部 unsafe 代码集中在这一个文件)
- 零分配路径解析: 路径按需切片遍历, 不再为每次 Get 分配临时切片 (path.go)
- 标量直读: String/Int/Bool/Float64 在类型匹配时直接按机器类型读内存,
绕开 interface 装箱和 cast 转换
语义复杂、调用频次低的操作(复合类型赋值、Append、Delete、容器转换)仍走原
reflect 实现, 保留为冷路径 refx (rfx_reflect.go), 避免重写引入行为偏差。
新增包级泛型函数 Get[T](r, path...), 按路径直接取出目标类型, 零内存分配。
语义与 r.Get(path...).Xxx() 严格等价, 不改动任何现有接口。
性能对比(同进程同数据, -benchmem -count=6 中位数):
- Get 嵌套 + String 150.6ns/7allocs -> 50.7ns/2allocs 2.97x
- Get 4 层深路径 234.1ns/10allocs -> 68.9ns/2allocs 3.40x
- Set 单层 65.8ns/2allocs -> 18.1ns/0allocs 3.64x
- Set 嵌套 122.1ns/3allocs -> 35.5ns/0allocs 3.44x
- Exists 127.4ns/5allocs -> 37.2ns/1alloc 3.42x
- 访问器 String 15.0ns/1alloc -> 1.3ns/0allocs 11.8x
- Get[string] 泛型直取 -> 29.9ns/0allocs 5.04x
两处不快: map 键访问 1.25x(map 无稳定布局, 仍走 reflect);
New 构造 0.67x(多一次描述符缓存查找, 一次性成本)。
内存安全: 未导出字段在读和写两处显式拦截 —— reflect.NewAt 构造的 Value
不带只读标记, 语言层面的导出规则保护在 unsafe 路径上失效, 必须自己拦。
不变式与评审要点见 unsafeptr.go 顶部注释。
测试: 新增 703 个用例全部通过, 含 go test -race。
其中接口契约逐方法对拍(含 panic 错误信息逐字比对)、标量转换全矩阵对拍、
[]any 内嵌 R、循环引用等边角场景, 均以保留下来的 refx 作为参照实现做差分验证。
合并过程中据此发现并修复 11 处行为偏差。
|
2026-08-28 16:37:04 +08:00 |
|
what
|
1f48635da3
|
fix: New()/Array() 正确处理 Nil 及已经是 R 的元素,不再 panic/重复包装
New(nil) 之前会 panic,现在返回 Nil(新增的 R 空实现单例,所有操作都是
安全的空操作/零值,不用调用方每次都判空)。New([]R{...}) 和 Array() 遇到
元素本身已经是 R(包括 Nil)时直接透传,不再重新拿 reflect.Value 包一层,
避免丢失原有的空值语义或类型信息。
|
2026-08-20 17:28:57 +08:00 |
|
what
|
3915bee7b8
|
feat: Slice方法支持JSON字符串自动解析
当Slice()方法遇到字符串类型且内容以'['开头时,会自动尝试JSON解析为切片。
这使得处理JSON格式的数组字符串更加便捷。
|
2026-01-12 15:04:42 +08:00 |
|
what
|
39da1d55dd
|
feat: 添加 Lookuper 接口和 MustLookup 方法
- 新增 Lookuper 接口,提供 Lookup 和 MustLookup 两种路径查找方式
- Accessor 接口继承 Lookuper,保持向后兼容
- MustLookup 在路径不存在时返回 Nil 访问器,简化调用代码
- 更新 fieldx.Schema 使用 Lookuper 接口,支持更灵活的数据源
- 添加 Required 字段选项,控制字段不存在时的行为
|
2026-01-05 16:59:31 +08:00 |
|
what
|
b73099d205
|
refactor: 改进错误处理,使用预定义错误替代硬编码字符串
- fieldx.Schema.Generate: 添加 panic 捕获机制,优雅处理 reflux.New 的异常
- fieldx.Schema.Generate: 支持 any 类型参数,增强通用性
- reflux.New: 使用预定义错误(ErrInvalidValue, ErrTargetNilPointer, NewErrUnsupportedTargetType)替代硬编码错误字符串
- 提高错误信息的一致性和可读性
|
2025-12-26 21:15:31 +08:00 |
|
what
|
a6d3e34e53
|
feat: 添加 fieldx 包,支持基于 Schema 的对象生成
新增 fieldx 包,提供基于预定义 Schema 生成 map[string]any 对象的功能。
主要特性:
- 支持固定值字段 (string)、字段引用 (field) 和嵌套对象 (object)
- 支持点号分隔的嵌套路径访问 (如 "user.name")
- 提供多种 Schema 创建方式 (JSON、Map、编程方式)
- 完善的错误处理和文档示例
|
2025-12-26 20:30:25 +08:00 |
|
what
|
d233fc319b
|
feat: 支持嵌套 R 和 valuex.Accessor 对象的路径访问
- 添加 unwrapAccessor 统一处理 Accessor 解引用
- 添加 deref/derefWithAccessor/derefValue 封装重复的解引用逻辑
- getValueByPath 支持穿透 R/Accessor 对象访问嵌套路径
- setNestedValue 支持在 R/Accessor 对象中设置嵌套值
- CloneValue 和 cloneElement 正确克隆 Accessor 底层值
- 支持在 map/struct/slice 中嵌套 R 对象并通过路径访问
- 添加完整测试覆盖 map/struct/slice/深度嵌套等场景
- 减少 38 行重复代码,提高代码可维护性
|
2025-12-24 16:37:12 +08:00 |
|
what
|
c62b07a119
|
refactor: 简化 normalizeInputValue 类型匹配逻辑
由于 R 接口继承 valuex.Accessor,无需单独处理 R 类型
使用 valuex.Accessor 统一处理即可,减少冗余代码
|
2025-12-16 16:19:29 +08:00 |
|
what
|
baad0cadfc
|
feat: 完善 normalizeInputValue 支持 valuex.Accessor 并优化代码
- 在 valuex.Accessor 接口中添加 Raw() 方法
- normalizeInputValue 支持 valuex.Accessor 和 []valuex.Accessor 类型
- 提取 normalizeAccessorSlice 泛型函数消除重复代码
- 使用 switch 语句替代 if-else 链提高可读性
- 添加相关测试用例确保功能正确性
|
2025-12-16 16:14:46 +08:00 |
|
what
|
7d17293df3
|
feat: 增强错误处理与示例
|
2025-12-09 20:06:56 +08:00 |
|
what
|
72d670be0b
|
feat: 增强 map 大小写不敏感支持和函数重命名
- 新增 tryMapFieldKey 函数,返回 map 中实际存在的键(支持大小写转换)
- 优化 setFieldValue 方法,使用 tryMapFieldKey 查找已存在字段并更新
- 优化 setNestedValue 方法,修复嵌套 map 大小写处理和 interface 包装问题
- 重命名函数以提高代码清晰度:
- tryStructField → tryStructFieldValue
- tryMapField → tryMapFieldValue
- tryMapFieldWithKey → tryMapFieldKey
- 新增 rfx_map_case_test.go 包含 16 个测试用例,覆盖基本、嵌套、边界等场景
|
2025-12-09 16:55:13 +08:00 |
|
what
|
fbba6f9a30
|
feat: 增强 nil 值处理能力
主要改进:
- 简化 setValue 方法中的 nil 值处理逻辑,统一设置为目标类型的零值
- 修复 setFieldValue 方法中 map 类型设置 nil 值时的问题
- 新增完整的 nil 值设置测试,覆盖所有 Go 基础类型和复合类型
测试覆盖:
- 指针、接口、切片、map、channel、func 等可空类型设置为 nil
- int/uint 系列、float 系列、bool、string 等基础类型设置为零值
- 嵌套结构体和 map 中的 nil 值设置
|
2025-12-09 15:11:18 +08:00 |
|
what
|
6e3593f188
|
feat: 优化 setValue 方法支持 nil 值处理
改进 setValue 方法在处理 nil 值时的行为:
- 对于可空类型(指针、接口、切片、map 等)设置为零值而非失败
- 对于基础类型(int、string、bool 等)继续执行 cast 转换逻辑
- 修复 val 无效时调用 val.Type() 的潜在空指针问题
|
2025-12-09 14:56:37 +08:00 |
|
what
|
2b7ac003a8
|
feat: Accessor 支持
|
2025-12-08 17:25:44 +08:00 |
|
what
|
bacec92841
|
feat: Append 方法支持 R 接口包装的指针类型
增强 setValue 函数,支持将 R 接口包装的指针值追加到非指针类型的切片中。当源值是指针但目标不是指针时,自动解引用后再赋值,使得 New(&item) 可以追加到 []Item 类型的切片。同时统一使用 Raw() 方法替代 Value() 方法名。
|
2025-12-08 17:24:45 +08:00 |
|
what
|
f5f261e541
|
feat: R 接口支持 JSON 序列化和反序列化
实现功能:
- R 接口继承 json.Marshaler 和 json.Unmarshaler 接口
- MarshalJSON(): 将 R 实例序列化为 JSON 字节数组
- UnmarshalJSON(): 从 JSON 字节数组反序列化到 R 实例
核心特性:
- 支持 struct、map、slice 等所有类型的 JSON 序列化
- 支持嵌套结构的序列化和反序列化
- 自动智能类型转换(如 JSON 数字 float64 -> int/int64)
- 可以对嵌套字段单独序列化(如 rfx.Get("Address"))
测试覆盖:
- TestJSONMarshal: 测试各种类型的序列化
- TestJSONUnmarshal: 测试各种类型的反序列化
- TestJSONRoundTrip: 测试序列化和反序列化的往返一致性
文档更新:
- 在 README 特性列表中添加 JSON 序列化说明
- 新增"JSON 序列化和反序列化"章节
- 包含完整的使用示例和最佳实践
- 说明使用场景:API通信、配置持久化、数据传输、缓存、消息队列等
|
2025-12-08 17:22:05 +08:00 |
|
what
|
a6a936c07c
|
feat: 增强 map 类型转换的容错能力
优化了所有 map 类型转换方法,采用三层转换策略:
1. 优先使用 cast 库进行类型转换
2. cast 失败后,通过 Keys() 和 Get() 进行自定义转换
3. 转换失败时提供完整的错误信息(包含 cast 错误和自定义转换错误)
优化的方法:
- StringMapString()
- StringMapStringSlice()
- StringMapBool()
- StringMapInt()
- StringMapInt64()
- StringMap()
这使得 struct 类型也能成功转换为 map 类型,增强了类型转换的灵活性。
|
2025-12-08 11:16:44 +08:00 |
|
what
|
9e1bc55a8c
|
feat: 增强类型转换能力和代码重构
核心改进:
1. 新增 normalizeInputValue 函数
- 统一处理输入值的规范化,支持 R 接口、[]R 切片、reflect.Value
- 避免重复封装,提升性能和类型安全性
2. 重构 getValueByPath 为独立函数
- 从 rfx 方法提取为独立函数,提高代码复用性
- 更好的职责分离,便于维护和测试
3. 显著增强 setValue 方法的类型转换能力
- 支持切片类型转换:[]any -> []T,自动转换每个元素
- 支持结构体类型转换:map -> struct 或 struct -> struct,按字段名匹配
- 保持指针切片的引用语义,避免不必要的对象复制
4. 新增 tryMapField 函数
- 支持 Map 键名的大小写不敏感访问
- 首字母大写的键会自动尝试小写版本(如 "Host" -> "host")
5. 新增 lowercaseFirst 辅助函数
- 用于首字母小写转换,配合 Map 键名查找
6. 更新测试用例
- 新增指针切片的使用示例
- 展示 []any 包含指针元素的场景
7. 文档全面更新
- 新增"高级类型转换"章节,详细说明切片、结构体、指针切片等转换
- 更新特性列表,突出增强的类型转换能力和 R 接口集成
- 补充 Map 大小写不敏感访问的说明
影响范围:
- reflux.go: 使用 normalizeInputValue 统一输入处理
- rfx.go: 重构并增强 setValue、getValueByPath 等核心方法
- util.go: 新增多个辅助函数,代码行数增加 160 行
- rfx_example_test.go: 新增指针切片测试用例
向后兼容:完全兼容现有 API,仅增强内部实现和类型转换能力
|
2025-12-05 11:12:11 +08:00 |
|
what
|
243d1ffac8
|
feat: 在 rfx.String() 中,先尝试用 cast.ToStringE 将当前值转为字符串,如果失败则增加了一个兜底逻辑:尝试使用 json.Marshal 将当前值序列化为 JSON 字符串并返回
|
2025-12-04 14:09:23 +08:00 |
|
what
|
b373dde7f7
|
feat: 支持切片追加及 -1 头部插入
|
2025-12-04 11:28:18 +08:00 |
|
what
|
cbe079ddcd
|
feat: 支持反射设置指针类型字段
- 如果目标字段是指针类型,它会尝试直接赋值(如果类型兼容),或创建一个新指针并递归设置其指向的值。
- `rfx_example_test.go` 中新增了测试用例,以验证对 `*string` 等指针字段的设置功能。
|
2025-12-04 11:25:44 +08:00 |
|
what
|
f9e7f8e781
|
fix: 修复深度克隆时 map/slice 中基本类型值被错误存储为指针的问题
- 提取 cloneSequence 函数统一处理 slice/array 克隆
- 提取 cloneElement 函数处理单个元素克隆
- 提取 needsDeepClone 函数判断是否需要深度克隆
- 减少代码重复,提高可维护性
为 ExampleNew_withValue* 系列测试添加 New() 后的输出,
清晰展示深度克隆后的初始状态和值类型正确性。
|
2025-12-03 10:20:15 +08:00 |
|
what
|
8fbc859e74
|
[feat] README.md 更新
|
2025-12-02 21:14:16 +08:00 |
|
what
|
97d41fa6d8
|
feat: 完善 New 方法支持指针和值参数,新增 interface 类型支持
- 支持指针模式: New(&data) - 直接修改原始数据
- 支持值模式: New(data) - 创建深度克隆,不影响原始数据
- 新增 interface{} 类型支持,自动解析到实际类型
- 对 map 和 slice 等引用类型也进行完全深度克隆
- 新增 9 个单元测试覆盖指针/值/interface 场景
- 新增 9 个示例测试展示各种用法
- 所有测试通过,保持性能
- 更新 README.md 详细说明指针/值传递的区别
- 新增 interface 类型使用示例
- 新增泛型数据处理使用场景
- 更新注意事项说明
- 使用递归解引用处理 interface 和指针类型
- 利用 DeepClone 确保引用类型的完全独立
- 保持向后兼容,现有代码无需修改
|
2025-12-02 21:08:33 +08:00 |
|
what
|
d9f178020a
|
first commit
|
2025-12-02 19:52:29 +08:00 |
|