Go Slice Tutorial

In this Go tutorial we learn how to reference an array with slices. We learn how to create slices from arrays, how to create empty slices as well as subslices of slices.

We also discuss how to get the length and capacity of a slice, how to add values to a slice, and how to copy values to an empty slice.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is a Slice in Go

A slice is a reference to an array. A slice doesn’t store any data but instead references the data of an array.

If we change the elements of a slice, it will also modify the elements in the array that the slice references. If another slice is referencing the same array, its values will also change.

Example:
package main

import "fmt"

func main() {

    // array
    var employee = [] string {
        "John",
        "Jane",
        "Jack",
        "Jill",
    }

    fmt.Printf("Array: %s\n", employee)

    // slice elements 0 to < 2
    // from the employee array
    // and store them here
    slice := employee[0:2]

    fmt.Printf("Slice: %s\n", employee)

    // modifying an element
    // in the slice
    slice[0] = "Banana"

    // modifies the element
    // in the employee array
    fmt.Printf("Array: %s\n", employee)
}

How to define a nil slice

Go provides us with multiple methods of defining a slice.

We can define a slice with an unspecified size, similar to how we would create an array.

Syntax:
 var slice_name [] type

When we create a slice using the method above, it will be initialized as nil.

nil represents the absense of a value.

Example:
package main

import "fmt"

func main() {

    var slice [] int

    if (slice == nil) {

        fmt.Println("slice is nil")
    }
}

We can also use the make() function. The make() function takes 3 arguments, the type, length, and capacity.

Syntax:
 var slice_name = make([] type, length, capacity)

A slice created with the make() function will be initialized with a default value for its type.

For example, a slice of type int will have values of 0, and a slice of type string will have values of “”.

Example:
package main

import "fmt"

func main() {

    var slice = make([] int, 5, 5)

    fmt.Println(slice)
}

How to create a subslice

We can specify upper and lower-bound values to create a subslice. Bounds are specified between square brackets and are separated by a colon.

Syntax:
 slice_name := array_or_slice_name[lower-bound:upper-bound]

The lower bound is where the slice should start, the upper bound is where the slice should stop.

As an example, let’s consider an array with 5 elements. If we specify the lower-bound to be 0, the slice will start at element 0.

If we specify our upper-bound as 3, the slice will stop at element number 2. Essentially it works lower-bound to 1 less than upper-bound.

Example:
package main

import "fmt"

func main() {

    // array
    var employee = [] string {
        "John",
        "Jane",
        "Jack",
        "Jill",
    }

    // slice elements 2 and 3
    // of employee array
    slice := employee[2:4]

    // slice element 1
    // of slice
    subslice := slice[1:2]

    fmt.Printf("Array: %s\n", employee)
    fmt.Printf("Slice: %s\n", slice)
    fmt.Printf("Subslice: %s\n", subslice)
}

In the example above, we slice elements 2 and 3 from the array. Our slice then contains the names ‘Jack’ and ‘Jill’.

Then, we create a subslice with element 1 from the original slice, which is ‘Jill’.

Slice length and capacity

Two of the components of a slice is its length and its capacity.

  • Length is the total number of elements in the slice.
  • Capacity is the maximum size up to which the slice can expand.

Go provides us with two handy functions that return these values, len() and cap().

Syntax:
len(slice_name) // length
cap(slice_name) // capacity
Example:
package main

import "fmt"

func main() {

    // array
    var employee = [] string {
        "John",
        "Jane",
        "Jack",
        "Jill",
    }

    // slice only 2 elements
    slice := employee[2:4]

    fmt.Printf("Len: %d\nCap: %d\n", len(slice), cap(slice))
}

How to add values to a slice with append()

We can add a value to a slice by using the append() function.

The append function takes two arguments:

  • The slice that we want to add the value to
  • The value, which must be of the same type as the slice
Syntax:
 append(slice_name, value)
Example:
package main

import "fmt"

func main() {

    // array
    var employee = [] string {
        "John",
        "Jane",
        "Jack",
        "Jill",
    }

    // slice 2 elements
    slice := employee[2:4]

    // Add a value to the slice
    slice = append(slice, "Bananaman")

    fmt.Println(slice)
    fmt.Println(employee)
}

In the example above, we add a single string value to our slice.

How to copy values to an empty slice

Go provides us with the copy() function to copy values to an empty slice.

The copy() function accepts to arguments:

  • Destination
  • Source
Syntax:
 copy(destination, source)

Note that the empty slice that we are copying to, must have the same type as the source slice.

Example:
package main

import "fmt"

func main() {

    // array
    var employee = [] string {
        "John",
        "Jane",
        "Jack",
        "Jill",
    }

    // 2 empty elements
    var slice = make([] string, 2, 2)

    // Copy from employee to
    // empty slice
    result := copy(slice, employee)

    fmt.Printf("%d values copied\n", result)
    fmt.Println("Slice: ", slice)
    fmt.Println("Array: ", employee)
}

In the example above, we copy the first two element of the employee array into the empty slice.

It only copied two elements because the empty slice only has two elements, not because we specified it.

Summary: Points to remember

  • A slice is a reference to an array and doesn’t store any data.
  • If we change values in a slice, the underlying values in the array will change as well.
  • Empty slices are initialized with either nil or the zero value for its type (ie. int = 0, string = “”).
  • We can create a subslice of a slice.
  • We can get the length and capacity of a slice with the len() and cap() functions respectively.
  • To add a value to a slice, we use the append() function.
    • The appended value must have the same type as the slice.
  • To copy elements to an empty slice, we use the copy() function.
    • The destination is the first parameter, the source is the second parameter.
    • The destination slice must be of the same type as the source slice.