我正在使用golang。这是我的代码:
func main() {
quanPailie([]int{1, 2})
}
func quanPailie(nums []int) [][]int {
COUNT := len(nums)
//only one item
if COUNT == 1 {
return [][]int{nums}
}
insertItem(quanPailie(nums[:COUNT-1]), nums[COUNT-1])
return [][]int{}
}
func insertItem(res [][]int, insertNum int) {
fmt.Println("insertItem,res:", res, "insertNum", insertNum) //insertItem,res: [[1]] insertNum 2
for _, v := range res {
for i := 0; i < len(v); i++ {
fmt.Println("===before,v:", v)
c := append(v[:i], append([]int{insertNum}, v[i:]...)...)
fmt.Println("===after,v:", v)
fmt.Println("ccc", c)
}
}
}
令我困惑的是输出:
===before,v: [1]
===after,v: [2]
为什么v
的值会发生变化?希望可以有人帮帮我。非常感谢。
去游乐场:https://play.golang.org/p/wITYsGpX7U
修改
感谢icza的大力帮助,我想我已经理解了这个问题
而且,这是一个显示此问题的简单代码。
func test1() {
nums := []int{1, 2, 3}
_ = append(nums[:2], 4)
fmt.Println("test1:", nums)
//nums changes because the cap is big enought, the original array is modified.
}
func test2() {
nums := []int{1, 2, 3}
c := append(nums[:2], []int{4, 5, 6}...)
fmt.Println("test2:", nums)
fmt.Println("cc:", c)
//nums dont't change because the cap isn't big enought.
//a new array is allocated while the nums still points to the old array.
//Of course, the return value of append points to the new array.
}
答案 0 :(得分:3)
这是有问题的代码:
fmt.Println("===before,v:", v)
c := append(v[:i], append([]int{insertNum}, v[i:]...)...)
fmt.Println("===after,v:", v)
您问为什么v
在Println()
个语句之间发生了变化。
因为您使用的是内置append()
函数,所以引用其文档:
追加内置函数将元素附加到切片的末尾。 如果有足够的容量,则会复制目标以容纳新元素。如果没有,则会分配新的基础数组。 Append返回更新的切片。
因此,如果您追加的切片有足够的空间(容量)来容纳您想要追加的元素,则不会分配新切片,而是重新切片目标切片(将使用相同的底层数组)并附加将发生在那。
让我们检查一下容量:
fmt.Println("===before,v:", v, cap(v))
c := append(v[:i], append([]int{insertNum}, v[i:]...)...)
fmt.Println("===after,v:", v, cap(v))
输出:
===before,v: [1] 2
===after,v: [2] 2
v
切片的容量为2
。当for
循环开始时,i=0
,v[:i]
为v[:0]
,这是一个空切片(但具有容量2
),因此附加1或2个元素不会分配一个新的数组/切片,它将完成&#34;到位&#34;。这个&#34;到位&#34;是v
的第0个元素,因为v[:i]
是v[0:i]
的简写。因此,元素将从共享的基础数组中的v[0]
开始追加,因此v[0]
表示的元素将发生变化。
请注意,切片会产生一个切片,该切片与原始切片共享其底层支持数组(不会复制元素)。
如果您想避免这种情况,请使用或分配新的切片,copy原始内容并附加到新切片,例如:
src := []int{1, 2}
c := make([]int, len(src))
copy(c, src)
// Append something:
c = append(c, 3, 4)
fmt.Println(src) // [1 2] - src doesn't change
fmt.Println(c) // [1 2 3 4]