在保持其子切片

时间:2016-05-18 14:21:45

标签: memory-management go slice

我一直在试验切片。这是一个示例程序

for n := 1; n <= 10; n++ {
    a := make([]int, 0)
    for j := 0; j < n; j++ {
        a = append(a, 0)
    }
    b := a[:1]
    a = append(a, 0)
    a[0] = 1
    fmt.Println(n, b[0])
}

输出

1 0
2 0
3 1
4 0
5 1
6 1
7 1
8 0
9 1
10 1

我明白这里发生了什么。如果旧数组的长度不足,则行a = append(a, 0)将分配一个新数组,并且新数组的长度是原始数组的两倍。因此,如果n是2的幂,那么

a[0] = 1

不会更改b支持的数组,因为之前会在该行中分配新数组。

但是我在文档中找不到一个明确的声明,即新分配的数组总是有两倍的长度。这是否意味着我的代码依赖于实现?以这种方式在变量中存储另一个切片的片段是不好的做法,还是每次需要一个子片段时我应该只做a[j:k]

2 个答案:

答案 0 :(得分:2)

底层数组大小加倍是一个实现细节(一旦大小达到当前实现中的某个阈值,就不再成立)。因此,您不能依赖此选择性地更改b[0]

不幸的是,我不明白你的最后两个问题。子序列没有任何问题,它不依赖于显式(a[i:k])或隐式开始或停止索引(a[i:]a[:k]),因为这完全相同。

答案 1 :(得分:1)

你已经知道了答案。

  • 依赖于实现
  • 如果要更改基础数组/切片
  • ,则对子切片进行子切片是不好的做法
  • 最好在需要时明确使用子切片 - 它很便宜。

虽然好问题。谢谢分享。