Golang中如何复制包含指针的map
Golang中如何复制包含指针的map 我有一个包含指针的映射,想要复制/克隆它,然后修改复制后映射中的一些参数(同时不改变原始映射)。这里有一个简短的可运行示例: https://play.golang.org/p/LxPGXpedqei
问题在于,由于指针的存在,当我修改复制映射中的参数时,原始映射中的值也会随之改变。那么,如何正确地复制一个包含指针的映射呢?谢谢
2 回复
你的循环如下:
for key, value := range originalMap { //! 必须通过 key,value 这种方式进行,否则会关联到同一个 map
targetMap[key] = new(str)
targetMap[key] = value
}
你循环中的这部分代码创建了一个新的空 *str 结构体,但随后你又通过将原始的 value 指针复制到 targetMap 中覆盖了它。
我认为你想要做的应该是更像这样:
// ------ 从原始 map 复制到目标 map
for key, value := range originalMap { //! 必须通过 key,value 这种方式进行,否则会关联到同一个 map
newStr := new(str) // 创建新的 str
*newStr = *value // 解引用 value 指针
// 并将 str 的值
// 复制到 newStr。
targetMap[key] = newStr
}
更多关于Golang中如何复制包含指针的map的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
要正确复制包含指针的映射,你需要对映射中的每个指针值进行深拷贝。以下是几种实现方式:
方法1:手动深拷贝每个指针
package main
import "fmt"
type Data struct {
Value int
}
func copyMapWithPointers(original map[string]*Data) map[string]*Data {
copy := make(map[string]*Data, len(original))
for k, v := range original {
// 创建新的指针,复制结构体内容
copy[k] = &Data{Value: v.Value}
}
return copy
}
func main() {
original := map[string]*Data{
"a": {Value: 1},
"b": {Value: 2},
}
copied := copyMapWithPointers(original)
copied["a"].Value = 100
fmt.Println("Original:", original["a"].Value) // 输出: 1
fmt.Println("Copied:", copied["a"].Value) // 输出: 100
}
方法2:使用反射进行通用深拷贝
package main
import (
"fmt"
"reflect"
)
type Data struct {
Value int
}
func deepCopyMap(original interface{}) interface{} {
origValue := reflect.ValueOf(original)
if origValue.Kind() != reflect.Map {
return original
}
copy := reflect.MakeMap(origValue.Type())
for _, key := range origValue.MapKeys() {
origElem := origValue.MapIndex(key)
if origElem.Kind() == reflect.Ptr {
// 获取指针指向的值
elemValue := origElem.Elem()
// 创建新指针并复制值
newPtr := reflect.New(elemValue.Type())
newPtr.Elem().Set(elemValue)
copy.SetMapIndex(key, newPtr)
} else {
copy.SetMapIndex(key, origElem)
}
}
return copy.Interface()
}
func main() {
original := map[string]*Data{
"x": {Value: 10},
"y": {Value: 20},
}
copied := deepCopyMap(original).(map[string]*Data)
copied["x"].Value = 999
fmt.Println("Original:", original["x"].Value) // 输出: 10
fmt.Println("Copied:", copied["x"].Value) // 输出: 999
}
方法3:使用序列化/反序列化(JSON)
package main
import (
"encoding/json"
"fmt"
)
type Data struct {
Value int
}
func copyMapViaJSON(original map[string]*Data) (map[string]*Data, error) {
var copied map[string]*Data
// 序列化为JSON
data, err := json.Marshal(original)
if err != nil {
return nil, err
}
// 反序列化创建新副本
err = json.Unmarshal(data, &copied)
if err != nil {
return nil, err
}
return copied, nil
}
func main() {
original := map[string]*Data{
"key1": {Value: 42},
"key2": {Value: 84},
}
copied, err := copyMapViaJSON(original)
if err != nil {
panic(err)
}
copied["key1"].Value = 0
fmt.Println("Original:", original["key1"].Value) // 输出: 42
fmt.Println("Copied:", copied["key1"].Value) // 输出: 0
}
方法4:为结构体实现Clone方法
package main
import "fmt"
type Data struct {
Value int
Nested *NestedData
}
type NestedData struct {
Text string
}
func (d *Data) Clone() *Data {
cloned := &Data{
Value: d.Value,
}
if d.Nested != nil {
cloned.Nested = &NestedData{
Text: d.Nested.Text,
}
}
return cloned
}
func copyMapWithClone(original map[string]*Data) map[string]*Data {
copy := make(map[string]*Data, len(original))
for k, v := range original {
copy[k] = v.Clone()
}
return copy
}
func main() {
original := map[string]*Data{
"item": {
Value: 5,
Nested: &NestedData{Text: "hello"},
},
}
copied := copyMapWithClone(original)
copied["item"].Value = 50
copied["item"].Nested.Text = "world"
fmt.Println("Original value:", original["item"].Value) // 输出: 5
fmt.Println("Original text:", original["item"].Nested.Text) // 输出: hello
fmt.Println("Copied value:", copied["item"].Value) // 输出: 50
fmt.Println("Copied text:", copied["item"].Nested.Text) // 输出: world
}
方法1最简单直接,适合结构明确的情况。方法2更通用但性能较低。方法3适合需要序列化的场景。方法4在结构体复杂时最清晰可控。

