考虑这段代码:
package main
import (
"fmt"
)
func main() {
fmt.Println(Part(11))
}
func Part(n int) string {
enumResult := [][]int{}
enum(n, n, []int{}, &enumResult)
fmt.Println(enumResult)
fmt.Println(40, enumResult[40])
return ""
}
var abc int = 0
func enum(n int, top int, pre []int, result *[][]int) {
var i int
if n > top {
i = top
} else {
i = n
}
for ; i > 0; i-- {
tempResult := append(pre, i)
if n-i == 0 {
/* if tempResult[0] == 3 && tempResult[1] == 3 && tempResult[2] == 3 && tempResult[3] == 2 {
tempResult = append(tempResult, 12345)
}*/
fmt.Println(abc, tempResult)
abc++
*result = append(*result, tempResult)
} else {
enum(n-i, i, tempResult, result)
}
}
}
当我运行这段代码时
我将值“[3,3,3,2]”附加到“enumResult”
但是如果我检查 'enumResult' 的值,则会出现 '[3,3,3,1]'
它的索引是 40 =>enumResult[40] (其他值正确)
我不知道为什么会这样 你能给我解释一下为什么吗?
最佳答案
确实是append
的问题。
关于append
有两件事。首先,append
不一定复制内存。作为spec指定:
If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.
如果您不清楚,这可能会导致意外行为。 Playground 示例:https://play.golang.org/p/7A3JR-5IX8o
第二部分是,当append
复制内存时,它会增加 slice 的容量。然而,它不会只增加 1。 Playground 示例:https://play.golang.org/p/STr9jMqORUz
slice 增长多少 append
是未记录的,被认为是实现细节。但是直到 Go 1.10,它遵循这个规则:
Go slices grow by doubling until size 1024, after which they grow by 25% each time.
请注意,启用竞争检测器时,这可能会改变。增长 slice 的代码位于$GOROOT/src/runtime/slice.go
中的growslice
函数。
现在回到问题。现在应该很清楚,由于之前 append
的 slice 增长,您的代码确实从具有足够容量的同一 slice append
。为了解决它,制作一个新的 slice 并复制内存。
tempResult := make([]int,len(pre)+1)
copy(tempResult,pre)
tempResult[len(pre)] = i
关于go - 将值附加到 slice 时,值与原始值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50859784/