2 回答

TA贡献1783条经验 获得超4个赞
// Remove this line and it works fine
//initialSlice = append(initialSlice, "I'm")
fmt.Printf("Slice Value : %p - %d\n", initialSlice, cap(initialSlice))
...
for i := 0; i < 2; i++ {
slice := append(initialSlice, strconv.Itoa(i))
fmt.Printf("Slice Value : %p - %p\n", slice, initialSlice)
...
}
如上打印initialSlice和slice的addressand 。当取消注释附加时,我是 line。它输出如下:capacity
Slice Value : 0xc00009c000 - 2
Slice Value : 0xc0000a6000 - 0xc00009c000
Slice Value : 0xc00009e040 - 0xc00009c000
如果注释该行,则输出如下:
Slice Value : 0xc00009e000 - 4
Slice Value : 0xc00009e000 - 0xc00009e000
Slice Value : 0xc00009e000 - 0xc00009e000
然后为什么它在评论该行时按预期输出?
因为在这个场景中,initialSlice的容量是2。当追加新元素时将分配一个新的底层数组,因为它没有足够的空间来实现追加操作。
当您取消注释该行时,initialSlice的容量为4,它将就地修改数组。
参考:附加文档
append 内置函数将元素附加到切片的末尾。如果它有足够的容量,则重新划分目标以容纳新元素。如果没有,将分配一个新的底层数组。Append 返回更新后的切片。因此有必要将 append 的结果存储在保存切片本身的变量中: slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...) 作为一种特殊情况,合法的将字符串附加到字节切片,如下所示: slice = append([]byte("hello "), "world"...)

TA贡献1786条经验 获得超13个赞
切片基于指向数组的指针、长度和容量。您slice在sliceWrappers第一次迭代中放入(因此它包含指向数组的指针)。在第二次迭代中,append(initialSlice, strconv.Itoa(i))调用更改了同一个数组中的值,因为内存位置没有改变。在第一次和第二次迭代中都指向这个数组slice,所以最终的两个切片都sliceWrappers指向相同的数据。
您可以通过在将数据添加到之前将数据复制到新切片来避免这种情况sliceWrappers:
for i := 0; i < 2; i++ {
slice := append(initialSlice, strconv.Itoa(i))
fmt.Printf("Slice Value : %+v, Initial Value : %+v\n", slice, initialSlice)
copiedSlice := make([]string, len(slice))
copy(copiedSlice, slice)
sliceWrappers = append(sliceWrappers, copiedSlice)
}
这给出了预期的输出:
Slice Value : [hi there I'm 0], Initial Value : [hi there I'm]
Slice Value : [hi there I'm 1], Initial Value : [hi there I'm]
[hi there I'm 0]
[hi there I'm 1]
至于删除线initialSlice = append(initialSlice, "I'm"):当您附加到切片时,它将检查它是否可以在容量内适应新长度。如果没有,它将分配一个新数组(从而分配新的内存位置)。包含“hi there”的较短切片已达到其容量,附加到它将分配一个新数组并创建一个容量更大的切片。
如果您initialSlice = append(initialSlice, "I'm")的程序中有该行,则新数组将在循环之前分配。循环内的append(...)s 不会导致新的分配。
如果您的程序中没有该行,append(...)则循环内的 s 将导致新的分配,因此每个最终都会有不同的内存位置,这就是它们不会相互覆盖的原因。
我的来源是Go Slices:用法和内部结构 https://blog.golang.org/slices-intro#TOC_4。
- 2 回答
- 0 关注
- 119 浏览
添加回答
举报