切片符号a [low:high:max]的用处?

问题描述 投票:1回答:1

通过使用full slice notation b = a[low:high:max],可以获得容量比分配的切片a小的切片。切片b的容量为max - low,元素存储将与a共享(不进行复制)。 max - low必须小于或等于cap(a),否则我们会感到恐慌:

a := make([]byte, 8)
b := a[:3:10]

panic: runtime error: slice bounds out of range [::10] with capacity 8

获得较小容量的切片的可能性有什么用?

我发现的唯一有用的应用程序是使用append强制切片的副本,从而以减小的容量绕过切片的容量。

    a := []int{1, 2, 3, 4, 5}
    b := a[1:3:3]
    fmt.Println("a:", a, "b:",b, "cap(b):", cap(b)) // -> a: [1 2 3 4 5] b: [2 3] cap(b): 2
    b[0] = 6
    fmt.Println("a:", a, "b:",b, "cap(b):", cap(b)) // -> a: [1 6 3 4 5] b: [6 3] cap(b): 2
    b = append(b, 7) // copy slice elements and extends capacity of b
    fmt.Println("a:", a, "b:",b, "cap(b):", cap(b)) // -> a: [1 6 3 4 5] b: [6 3 7] cap(b): 4
    b[1] = 8
    fmt.Println("a:", a, "b:",b, "cap(b):", cap(b)) // -> a: [1 6 3 4 5] b: [6 8 7] cap(b): 4

请注意,此类副本并不明显,需要注释以使其对读者可见。

另一个有用的应用程序吗?

go slice
1个回答
2
投票

它确实在附加上强加了一个副本,但是它的作用是[[略]。如果使用它,则可以将切片传递给一些未知的代码段,因为该代码将无法使用该切片读取或写入超出所需范围的底层数组。

通过普通切片表达式创建的切片将具有足够的容量,可以到达对其进行切片的数组或切片的末尾,因此调用方可以对其进行重新切片,使其达到对其进行访问的能力。完整的切片表达式使此操作不可能(或超出特定点也无法实现)。

这不是

安全

措施。程序中的其他代码当然可以弄清楚如何使用unsafe以一种或另一种方式在片的末尾进行读取或写入。这只是防止意外副作用的一种方法。如果要在您关心的某些数据的中间调用带有切片的函数,并且该函数可能将append扩展到切片或以其他方式扩展切片,则使用完整切片表达式来限制容量是明智的选择。

0
投票

完整的切片符号使您可以限制切片的容量。这允许垃圾回收器释放后备数组的未引用部分(假设没有其他引用对象)。这可以帮助减少程序对内存的使用。另一个用途是,如果追加超出其新容量,则避免覆盖与另一个片共享的支持数组。

尽管您的示例代码是错误的。完成b := a[2:3:4]后,b的长度为1(3-2),容量为2(4-2)。因此,当您写入b = append(b, 7)时,可以将b的长度增加到2,而不会超出其容量。因此没有副本。

© www.soinside.com 2019 - 2024. All rights reserved.