Re-slicing slices in Golang

Note that in go 1.2 (Q4 2013, 1.2rc1 is available now), you can associate to a slice a capacity of its own (instead of a capacity deduced from the underlying array).

See "Three-index slices", and the design document.

A slicing operation creates a new slice by describing a contiguous section of an already-created array or slice:

var array [10]int
slice := array[2:4]

The capacity of the slice is the maximum number of elements that the slice may hold, even after reslicing; it reflects the size of the underlying array.
In this example, the capacity of the slice variable is 8.

(capacity of the underlying array minus the position of the start of the slice in the array)

array : [0 0 0 0 0 0 0 0 0 0]
 array : <---- capacity --->
 slice :    [0 0]
 slice :    <-- capacity --> 8 (10-2)

Go 1.2 adds new syntax to allow a slicing operation to specify the capacity as well as the length.
A second colon introduces the capacity value, which must be less than or equal to the capacity of the source slice or array, adjusted for the origin.

For instance,

slice = array[2:4:6]

array : [0 0 0 0 0 0 0 0 0 0]
 array : <---- capacity --->   10
 slice :    [0 0]
 slice :    <- cap->           4 (6-2)

sets the slice to have the same length as in the earlier example but its capacity is now only 4 elements (6-2).
It is impossible to use this new slice value to access the last two elements of the original array.

The main argument is to give programmers more control over append.

a[i : j : k]

That slice has:

  • indices starting at 0
  • length equals to j - i
  • capacity equals to k - i

The evaluation panics if i <= j <= k <= cap(a) is not true.


c is a slice taken from the array b. This isn't a copy, but just a window over the 2 first elements of b.

As b has a capacity of 5, c could be extended to take the 3 other places (in fact it makes a new slice but over the same place in memory).

The maximal capacity of the slice is the capacity of the underlying array minus the position of the start of the slice in the array :

 array : [0 0 0 0 0 0 0 0 0 0 0 0]
 array :  <----   capacity   --->
 slice :     [0 0 0 0]
 slice :      <---- capacity ---> 

Maybe this program will make it more clear that c and d are just windows over b :

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // this is equivalent to d := b[1:5]
    d[0] = 1
    printSlice("c", c)
    printSlice("d", d)
}

Output :

c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0] 

Tags:

Arrays

Slice