Slices

A slice is similar to an array, but it can grow when new elements are added.A slice always refers to an underlying array. What makes slices different fromarrays is that a slice is a pointer to an array; slices are referencetypes.

Reference types are created with make. We detail this furtherin .

That means that if you assign one slice to another, both refer to the _same_underlying array. For instance, if a function takes a slice argument, changes itmakes to the elements of the slice will be visible to the caller, analogous topassing a pointer to the underlying array. With: slice := make([]int, 10), youcreate a slice which can hold ten elements. Note that the underlying array isn’tspecified. A slice is always coupled to an array that has a fixed size. Forslices we define a capacity and a length The image below shows the creation of an array,then the creation of a slice. First we create an array of (m) elements of thetype int: var array[m]int .

Next, we create a slice from this array: slice := array[:n] . And now we have:

  • len(slice) == n
  • cap(slice) == m
  • len(array) == cap(array) == m

Array versus slice

An array versus a slice.

Given an array, or another slice, a new slice is created via a[n:m]. Thiscreates a new slice which refers to the variable a, starts at index n, andends before index m. It has length n - m.

  1. a := [...]int{1, 2, 3, 4, 5} 1
  2. s1 := a[2:4] 2
  3. s2 := a[1:5] 3
  4. s3 := a[:] 4
  5. s4 := a[:4] 5
  6. s5 := s2[:] 6
  7. s6 := a[2:4:5] 7

First we define 1 an array with five elements, from index 0 to 4.From this we create 2 a slice with the elements from index 2 to 3, this slices contains: 3, 4.Then we we create another slice 3 from a: with the elements from index 1 to 4,this contains: 2, 3, 4, 5.With a[:] 4 we create a slice with all the elements in the array. This is a shorthand for: a[0:len(a)].And with a[:4] 5 we create a slice with the elements from index0 to 3, this is short for: a[0:4], and gives us a slices that contains: 1, 2, 3, 4.With s2[:] we create a slice from the slice s2 6, note that s5 still refers to the array a.Finally, we create a slice with the elements from index 3 to 3 and also set the cap to 4 7.

When working with slices you can overrun the bounds, consider this code.

  1. package main
  2. func main() {
  3. var array [100]int 1
  4. slice := array[0:99] 2
  5. slice[98] = 1 3
  6. slice[99] = 2 4
  7. }

At 1 we create an array with a 100 elements, indexed from 0 to 99. Then at 2we create a slice that has index 0 to 98. We assign 1 to the 99th element 3 ofthe slice. This works as expected. But at 4 we dare to do the impossible, andand try to allocate something beyond the length of the slice and we are greetedwith a runtime error: Error: "throw: index out of range".

If you want to extend a slice, there are a couple of built-in functions thatmake life easier: append and copy. The append function appends zero or morevalues to a slice and returns the result: a slice with the same type as theoriginal. If the original slice isn’t big enough to fit the added values, appendwill allocate a new slice that is big enough. So the slice returned by appendmay refer to a different underlying array than the original slice does. Here’san example:

  1. s0 := []int{0, 0}
  2. s1 := append(s0, 2) 1
  3. s2 := append(s1, 3, 5, 7) 2
  4. s3 := append(s2, s0...) 3

At 1 we append a single element, making s1 equal to []int{0, 0, 2}. At 2we append multiple elements, making s2 equal to []int{0, 0, 2, 3, 5, 7}. Andat 3 we append a slice, giving us s3 equal to []int{0, 0, 2, 3, 5, 7, 0, 0}.Note the three dots used after s0…! This is needed make it clear explicit that you’re appending another slice, instead of a single value.

The copy function copies slice elements from a source to a destination, andreturns the number of elements it copied. This number is the minimum of thelength of the source and the length of the destination. For example:

  1. var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
  2. var s = make([]int, 6)
  3. n1 := copy(s, a[0:]) 1
  4. n2 := copy(s, s[2:]) 2

After 1, n1 is 6, and s is []int{0, 1, 2, 3, 4, 5}.And after 2, n2 is 4, and s is []int{2, 3, 4, 5, 4, 5}.