Golang中如何解决二维切片追加数组时被重复更新的问题?

Golang中如何解决二维切片追加数组时被重复更新的问题?

ansMap := map[[3]int]bool{}
// 经过一些操作后,我需要将键追加到 ans
ans := [][]int{}
// 所以我这样做
for pair := range ansMap {
	ans = append(ans, pair[:])  // 现在 ans 中填充了相同的切片
}

我对 Go 语言还比较陌生。我了解到,在追加切片时,传递的是指针,所以当 pairansMap 获取新值时,已经追加到 ans 中的旧 pair 也会被更新,最终导致 ans 中填充了相同的切片。

我该如何解决这个问题?


更多关于Golang中如何解决二维切片追加数组时被重复更新的问题?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好,@W-Qiu

对数组进行切片会继续复用该数组。你需要将元素复制到独立的切片中:

for pair := range ansMap {
    dup := make([]int, len(pair))
    copy(dup, pair[:])
    ans = append(ans, dup)
}

一种更高效的存储方式是使用一个单一的底层切片:

// 注意必须设置容量,否则结果会比使用独立切片更糟:
allPairs := make([]int, 0, len(ansMap)*3)
for pair := range ansMap {
    allPairs = append(allPairs, pair[:]...)
    ans = append(ans, allPairs[len(allPairs)-3:])
}

更多关于Golang中如何解决二维切片追加数组时被重复更新的问题?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于你使用了数组 [3]int 的切片视图 pair[:],这个切片始终指向当前循环变量 pair 的底层数组。由于循环变量 pair 在每次迭代中会被重用,导致所有追加的切片都指向同一个底层数组,最终都包含最后一次迭代的值。

解决方案是创建新的切片副本,而不是直接使用 pair[:]。以下是几种解决方法:

方法1:显式创建新切片

ans := [][]int{}
for pair := range ansMap {
    // 创建新的切片副本
    newSlice := make([]int, len(pair))
    copy(newSlice, pair[:])
    ans = append(ans, newSlice)
}

方法2:使用数组转换(Go 1.17+)

ans := [][]int{}
for pair := range ansMap {
    // 将数组转换为切片,创建新切片
    ans = append(ans, pair[:len(pair):len(pair)])
}

方法3:使用完整的切片表达式

ans := [][]int{}
for pair := range ansMap {
    // 使用完整切片表达式创建新切片
    ans = append(ans, pair[:len(pair):len(pair)])
}

方法4:直接使用数组并转换为切片

ans := [][]int{}
for pair := range ansMap {
    // 创建临时变量避免重用
    currentPair := pair
    ans = append(ans, currentPair[:])
}

完整示例

package main

import "fmt"

func main() {
    ansMap := map[[3]int]bool{
        {1, 2, 3}: true,
        {4, 5, 6}: true,
        {7, 8, 9}: true,
    }
    
    ans := [][]int{}
    for pair := range ansMap {
        // 正确方法:创建新切片副本
        newSlice := make([]int, len(pair))
        copy(newSlice, pair[:])
        ans = append(ans, newSlice)
    }
    
    fmt.Println(ans) // 输出不同的切片值
}

推荐使用方法1,它最清晰且性能良好。关键点是每次迭代都需要创建新的切片底层数组,避免所有切片共享同一个底层数组。

回到顶部