diff --git a/go.mod b/go.mod index 34a1761..32b8bf4 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/smarty/assertions v1.15.0 // indirect github.com/tidwall/match v1.2.0 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect golang.org/x/mod v0.9.0 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/tools v0.7.0 // indirect diff --git a/go.sum b/go.sum index 31ccf8c..07c7879 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,7 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= @@ -52,6 +53,8 @@ github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= diff --git a/op_array/util.go b/op_array/util.go index e7c1da7..5eec209 100644 --- a/op_array/util.go +++ b/op_array/util.go @@ -9,6 +9,7 @@ package op_array import ( "fmt" + "reflect" ) // ToMap 数组转map @@ -112,3 +113,34 @@ func Tree[ID comparable, Value any](dataList []Value, formatParentID func(v Valu } return rootData } + +// DeepClone 深度克隆一个数组, 每一个元素的地址均重新分配 +func DeepClone[Value any](dataList []Value) []Value { + v := *new(Value) + vType := reflect.TypeOf(v) + res := make([]Value, len(dataList)) + for i := 0; i < len(dataList); i++ { + newV := new(Value) + switch vType.Kind() { + case reflect.Ptr: + // 解引用, 并单独读取值后重新分配地址 + copyV := reflect.New(vType.Elem()).Elem() + copyV.Set(reflect.ValueOf(dataList[i]).Elem()) + *newV = copyV.Addr().Interface().(Value) + case reflect.Map: + mapVal := reflect.ValueOf(dataList[i]) + mapKeyList := mapVal.MapKeys() + newMap := reflect.MakeMap(vType) + for _, key := range mapKeyList { + // 通过键获取对应的值 + value := mapVal.MapIndex(key) + newMap.SetMapIndex(key, value) + } + *newV = newMap.Interface().(Value) + default: + *newV = dataList[i] + } + res[i] = *newV + } + return res +} diff --git a/op_array/util_test.go b/op_array/util_test.go index 7c057cf..d1848d0 100644 --- a/op_array/util_test.go +++ b/op_array/util_test.go @@ -8,6 +8,7 @@ package op_array import ( + "fmt" "testing" "git.zhangdeman.cn/zhangdeman/serialize" @@ -32,3 +33,38 @@ func TestTree(t *testing.T) { res := Tree(dataList, func(v Data) int { return v.ParentID }, func(v Data) int { return v.ID }) serialize.JSON.ConsoleOutput(res) } + +func TestClone(t *testing.T) { + type Data struct { + ID int `json:"id" dc:"数据ID"` + } + + // 字面结构体 + dataList := []Data{ + {ID: 1}, + {ID: 2}, + } + res := DeepClone(dataList) + fmt.Println(fmt.Sprintf("%p", &res[0]), fmt.Sprintf("%p", &dataList[0])) + fmt.Println(fmt.Sprintf("%p", &res[1]), fmt.Sprintf("%p", &dataList[1])) + + // 结构体指针 + dataList1 := []*Data{ + {ID: 1}, + {ID: 2}, + } + res1 := DeepClone(dataList1) + fmt.Println(fmt.Sprintf("%p", &res1[0]), fmt.Sprintf("%p", &dataList1[0])) + fmt.Println(fmt.Sprintf("%p", &res1[1]), fmt.Sprintf("%p", &dataList1[1])) + + // Map数据 + dataList2 := []map[string]any{ + {"id": 1}, + {"id": 2}, + } + res2 := DeepClone(dataList2) + fmt.Println(fmt.Sprintf("%p", &res2[0]), fmt.Sprintf("%p", &dataList2[0])) + fmt.Println(fmt.Sprintf("%p", &res2[1]), fmt.Sprintf("%p", &dataList2[1])) + serialize.JSON.ConsoleOutput(res2) + serialize.JSON.ConsoleOutput(dataList2) +}