feat: 完善 normalizeInputValue 支持 valuex.Accessor 并优化代码
- 在 valuex.Accessor 接口中添加 Raw() 方法 - normalizeInputValue 支持 valuex.Accessor 和 []valuex.Accessor 类型 - 提取 normalizeAccessorSlice 泛型函数消除重复代码 - 使用 switch 语句替代 if-else 链提高可读性 - 添加相关测试用例确保功能正确性
This commit is contained in:
parent
7d17293df3
commit
baad0cadfc
53
rfx_test.go
53
rfx_test.go
@ -2,7 +2,10 @@ package reflux
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/reflux/valuex"
|
||||
)
|
||||
|
||||
// 测试用的结构体
|
||||
@ -1422,3 +1425,53 @@ func TestSetValueChainWithCast(t *testing.T) {
|
||||
t.Errorf("Expected Score to be 95.5, got %f", user.Score)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalizeValuexAccessor 测试 normalizeInputValue 对 valuex.Accessor 的支持
|
||||
func TestNormalizeValuexAccessor(t *testing.T) {
|
||||
// 创建一个 R 实例
|
||||
data := map[string]any{
|
||||
"name": "Alice",
|
||||
"age": 30,
|
||||
}
|
||||
r := New(data)
|
||||
|
||||
// 测试 valuex.Accessor 类型
|
||||
rv, isPtr, err := normalizeInputValue(r)
|
||||
if err != nil {
|
||||
t.Fatalf("normalizeInputValue failed: %v", err)
|
||||
}
|
||||
if !isPtr {
|
||||
t.Error("Expected isPtr to be true for valuex.Accessor")
|
||||
}
|
||||
if !rv.IsValid() {
|
||||
t.Error("Expected valid reflect.Value")
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalizeValuexAccessorSlice 测试 normalizeInputValue 对 []valuex.Accessor 的支持
|
||||
func TestNormalizeValuexAccessorSlice(t *testing.T) {
|
||||
// 创建多个 R 实例
|
||||
r1 := New(map[string]any{"id": 1, "name": "Alice"})
|
||||
r2 := New(map[string]any{"id": 2, "name": "Bob"})
|
||||
|
||||
// 创建 []valuex.Accessor
|
||||
slice := []valuex.Accessor{r1, r2}
|
||||
|
||||
// 测试 []valuex.Accessor 类型
|
||||
rv, isPtr, err := normalizeInputValue(slice)
|
||||
if err != nil {
|
||||
t.Fatalf("normalizeInputValue failed: %v", err)
|
||||
}
|
||||
if !isPtr {
|
||||
t.Error("Expected isPtr to be true for []valuex.Accessor")
|
||||
}
|
||||
if !rv.IsValid() {
|
||||
t.Error("Expected valid reflect.Value")
|
||||
}
|
||||
if rv.Kind() != reflect.Slice {
|
||||
t.Errorf("Expected Slice kind, got %v", rv.Kind())
|
||||
}
|
||||
if rv.Len() != 2 {
|
||||
t.Errorf("Expected slice length 2, got %d", rv.Len())
|
||||
}
|
||||
}
|
||||
|
||||
64
util.go
64
util.go
@ -6,6 +6,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"git.fsdpf.net/go/reflux/valuex"
|
||||
)
|
||||
|
||||
// DeepClone 深度克隆一个 reflect.Value
|
||||
@ -335,20 +337,13 @@ func tryMapFieldKey(m reflect.Value, key string) reflect.Value {
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
// normalizeInputValue 规范化传入的任意值为 reflect.Value
|
||||
// 返回对应的 reflect.Value 以及是否应被视为指针(isPtr)
|
||||
func normalizeInputValue(v any) (reflect.Value, bool, error) {
|
||||
var rv reflect.Value
|
||||
var isPtr bool
|
||||
|
||||
if vv, ok := v.(R); ok {
|
||||
isPtr = true
|
||||
rv = vv.Raw()
|
||||
} else if vv, ok := v.([]R); ok {
|
||||
// 支持直接传入 []R,自动转换为底层切片
|
||||
// normalizeAccessorSlice 规范化 Accessor 切片为 reflect.Value
|
||||
// 这个辅助函数用于处理 []R 和 []valuex.Accessor 的共同逻辑
|
||||
func normalizeAccessorSlice[T valuex.Accessor](slice []T, typeName string) (reflect.Value, bool, error) {
|
||||
var elemType reflect.Type
|
||||
for _, it := range vv {
|
||||
if it == nil {
|
||||
for _, it := range slice {
|
||||
// 检查是否为 nil (通过 any 转换检查)
|
||||
if any(it) == nil {
|
||||
continue
|
||||
}
|
||||
val := it.Raw()
|
||||
@ -358,15 +353,16 @@ func normalizeInputValue(v any) (reflect.Value, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有元素都是 nil 或无效,退回到通用处理
|
||||
// 如果所有元素都是 nil 或无效,返回 nil
|
||||
if elemType == nil {
|
||||
rv = reflect.ValueOf(nil)
|
||||
} else {
|
||||
isPtr = true
|
||||
count := len(vv)
|
||||
rv = reflect.MakeSlice(reflect.SliceOf(elemType), count, count)
|
||||
for i, it := range vv {
|
||||
if it == nil {
|
||||
return reflect.ValueOf(nil), false, nil
|
||||
}
|
||||
|
||||
// 创建底层切片
|
||||
count := len(slice)
|
||||
rv := reflect.MakeSlice(reflect.SliceOf(elemType), count, count)
|
||||
for i, it := range slice {
|
||||
if any(it) == nil {
|
||||
continue
|
||||
}
|
||||
val := it.Raw()
|
||||
@ -374,15 +370,35 @@ func normalizeInputValue(v any) (reflect.Value, bool, error) {
|
||||
continue
|
||||
}
|
||||
if !val.Type().AssignableTo(elemType) {
|
||||
return rv, isPtr, fmt.Errorf("rfx: []R element type mismatch at index %d: got %s, want %s", i, val.Type(), elemType)
|
||||
return rv, true, fmt.Errorf("rfx: []%s element type mismatch at index %d: got %s, want %s", typeName, i, val.Type(), elemType)
|
||||
}
|
||||
rv.Index(i).Set(val)
|
||||
}
|
||||
|
||||
return rv, true, nil
|
||||
}
|
||||
} else if vv, ok := v.(reflect.Value); ok {
|
||||
|
||||
// normalizeInputValue 规范化传入的任意值为 reflect.Value
|
||||
// 返回对应的 reflect.Value 以及是否应被视为指针(isPtr)
|
||||
func normalizeInputValue(v any) (reflect.Value, bool, error) {
|
||||
var rv reflect.Value
|
||||
var isPtr bool
|
||||
|
||||
switch vv := v.(type) {
|
||||
case R:
|
||||
isPtr = true
|
||||
rv = vv.Raw()
|
||||
case valuex.Accessor:
|
||||
isPtr = true
|
||||
rv = vv.Raw()
|
||||
case []valuex.Accessor:
|
||||
return normalizeAccessorSlice(vv, "valuex.Accessor")
|
||||
case []R:
|
||||
return normalizeAccessorSlice(vv, "R")
|
||||
case reflect.Value:
|
||||
// 支持直接传入 reflect.Value,避免重复封装
|
||||
rv = vv
|
||||
} else {
|
||||
default:
|
||||
rv = reflect.ValueOf(v)
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
package valuex
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Accessor 为参数值转换相关接口
|
||||
type Accessor interface {
|
||||
// Lookup 根据路径查找并返回对应值的访问器
|
||||
Lookup(path string) (Accessor, bool)
|
||||
|
||||
// Raw 返回底层的 reflect.Value
|
||||
Raw() reflect.Value
|
||||
|
||||
// Ptr 返回指向当前值的指针
|
||||
Ptr() any
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package valuex
|
||||
|
||||
import "reflect"
|
||||
|
||||
// nilAccessor 是一个空实现,用于表示不存在或空值的访问器
|
||||
// 所有转换方法都会返回对应类型的零值
|
||||
type nilAccessor struct{}
|
||||
@ -12,6 +14,10 @@ func (n *nilAccessor) Lookup(path string) (Accessor, bool) {
|
||||
return n, false
|
||||
}
|
||||
|
||||
func (n *nilAccessor) Raw() reflect.Value {
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
// Ptr 返回 nil
|
||||
func (n *nilAccessor) Ptr() any {
|
||||
return nil
|
||||
|
||||
Loading…
Reference in New Issue
Block a user