feat: 支持切片追加及 -1 头部插入
This commit is contained in:
67
rfx.go
67
rfx.go
@@ -115,6 +115,42 @@ func (r *rfx) Set(key string, v any) R {
|
||||
return r
|
||||
}
|
||||
|
||||
// Append 追加指定路径的值
|
||||
// 参数 items 为要追加的值
|
||||
// 返回当前 R 实例以支持链式调用
|
||||
func (r *rfx) Append(items ...any) R {
|
||||
// 没有要追加的元素,直接返回
|
||||
if len(items) == 0 {
|
||||
return r
|
||||
}
|
||||
|
||||
target := r.getParentValue()
|
||||
for target.Kind() == reflect.Ptr || target.Kind() == reflect.Interface {
|
||||
if target.IsNil() {
|
||||
panic("rfx: cannot append to nil value")
|
||||
}
|
||||
target = target.Elem()
|
||||
}
|
||||
|
||||
if !target.IsValid() || target.Kind() != reflect.Slice {
|
||||
panic("rfx: Append only supports slice type")
|
||||
}
|
||||
|
||||
// 一次性构造所有要追加的元素,然后调用一次 reflect.Append
|
||||
elemType := target.Type().Elem()
|
||||
newValues := make([]reflect.Value, len(items))
|
||||
for i, item := range items {
|
||||
newElem := reflect.New(elemType).Elem()
|
||||
if !r.setValue(newElem, item) {
|
||||
panic("rfx: failed to append item to slice")
|
||||
}
|
||||
newValues[i] = newElem
|
||||
}
|
||||
|
||||
target.Set(reflect.Append(target, newValues...))
|
||||
return r
|
||||
}
|
||||
|
||||
// setNestedValue 递归设置嵌套值,特殊处理 map 中的 struct
|
||||
func (r *rfx) setNestedValue(current reflect.Value, keys []string, v any) bool {
|
||||
// 解引用指针和接口
|
||||
@@ -232,7 +268,36 @@ func (r *rfx) setFieldValue(target reflect.Value, key string, v any) bool {
|
||||
}
|
||||
target.SetMapIndex(reflect.ValueOf(key), val)
|
||||
return true
|
||||
case reflect.Slice, reflect.Array:
|
||||
case reflect.Slice:
|
||||
idx, err := strconv.Atoi(key)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 对于切片,支持使用索引 -1 追加新元素(插入到切片前面)
|
||||
if idx == -1 {
|
||||
elemType := target.Type().Elem()
|
||||
newElem := reflect.New(elemType).Elem()
|
||||
if !r.setValue(newElem, v) {
|
||||
return false
|
||||
}
|
||||
// 将新元素放在前面,原有元素顺序后移
|
||||
newSlice := reflect.MakeSlice(target.Type(), 0, target.Len()+1)
|
||||
newSlice = reflect.Append(newSlice, newElem)
|
||||
newSlice = reflect.AppendSlice(newSlice, target)
|
||||
target.Set(newSlice)
|
||||
return true
|
||||
}
|
||||
|
||||
if idx < 0 || idx >= target.Len() {
|
||||
return false
|
||||
}
|
||||
elem := target.Index(idx)
|
||||
if !elem.CanSet() {
|
||||
return false
|
||||
}
|
||||
return r.setValue(elem, v)
|
||||
case reflect.Array:
|
||||
idx, err := strconv.Atoi(key)
|
||||
if err != nil || idx < 0 || idx >= target.Len() {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user