You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言拷贝切片后修改副本却影响原切片问题求助

指针切片拷贝后修改副本影响原切片的问题解决

问题场景

想要实现拷贝切片、修改副本元素值后将副本追加到原切片,但运行代码后发现原切片元素也被修改,实际输出与预期不符。

原代码:

import "fmt"

type Item struct {
    name   string
    number int
}

func main() {
    names := []string{"a", "b"}
    numbers := []int{1, 2}

    items := []*Item{}

    for _, name := range names {
        item := &Item{name: name}
        items = append(items, item)
    }

    for n, i := range numbers {
        if n > 0 {
            fmt.Println(n, "make a copy of the items")
            itemCopies := make([]*Item, len(items))
            copy(itemCopies, items)

            fmt.Println(n, "set the numbers on the copies")
            for _, item := range itemCopies {
                item.number = i
            }

            fmt.Println(n, "append the copies to the original")
            items = append(items, itemCopies...)
        } else {
            fmt.Println(n, "first pass set all the items to the first number")
            for _, item := range items {
                item.number = i
            }
        }
    }

    for n, i := range items {
        fmt.Printf("%d %+v\n", n, *i)
    }
}

实际输出:

0 {name:a number:2}
1 {name:b number:2}
2 {name:a number:2}
3 {name:b number:2}

预期输出:

0 {name:a number:1}
1 {name:b number:1}
2 {name:a number:2}
3 {name:b number:2}

问题根源

你的切片类型是[]*Item,切片中存储的是指向Item结构体的指针。使用copy(itemCopies, items)时,只是把原切片里的指针值复制到了新切片中——原切片和副本切片的指针指向的是同一个Item结构体实例。当你修改副本中指针指向的number字段时,本质是修改了同一个结构体的内容,原切片的指针自然会读到修改后的值。

解决方案

需要对每个Item进行深度拷贝,也就是为每个元素创建新的Item结构体实例,而不是仅复制指针。修改拷贝逻辑后的完整代码:

import "fmt"

type Item struct {
    name   string
    number int
}

func main() {
    names := []string{"a", "b"}
    numbers := []int{1, 2}

    items := []*Item{}

    for _, name := range names {
        item := &Item{name: name}
        items = append(items, item)
    }

    for n, i := range numbers {
        if n > 0 {
            fmt.Println(n, "make a copy of the items")
            // 替换原copy逻辑,创建新的Item实例
            itemCopies := make([]*Item, len(items))
            for idx, item := range items {
                itemCopies[idx] = &Item{
                    name:   item.name,
                    number: item.number,
                }
            }

            fmt.Println(n, "set the numbers on the copies")
            for _, item := range itemCopies {
                item.number = i
            }

            fmt.Println(n, "append the copies to the original")
            items = append(items, itemCopies...)
        } else {
            fmt.Println(n, "first pass set all the items to the first number")
            for _, item := range items {
                item.number = i
            }
        }
    }

    for n, i := range items {
        fmt.Printf("%d %+v\n", n, *i)
    }
}

运行后输出符合预期:

0 {name:a number:1}
1 {name:b number:1}
2 {name:a number:2}
3 {name:b number:2}

内容的提问来源于stack exchange,提问作者Jonathan Kittell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 10:55:09