Start learning free

LESSON 94 OF 338 · ARRAYS I

Slice Length in Go: len() and the Last Element

Lesson Read the full explanation

We can get the length of a slice using the len() function:

ourArray := []int{50, 40, 30}

// Printing the length:
fmt.Println(len(ourArray)) // Output: 3

// Changing the slice:
ourArray = ourArray[:len(ourArray)-1]

// Printing the new length:
fmt.Println(len(ourArray)) // Output: 2

Using the length

We can use the length to access items from the end of a slice.

Because slices are 0-indexed, the index of the last item is length - 1:

ourArray := []int{50, 40, 30}

size := len(ourArray)

// Printing the last item:
fmt.Println(ourArray[size - 1]) // Output: 30

// Printing the second to last item:
fmt.Println(ourArray[size - 2]) // Output: 40

Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 3
    Ctrl + Enter to check

    GO · ARRAYS I

    Array Length in Go, explained

    The len function

    To find out how many elements a slice holds, pass it to the built-in function len:

    ourArray := []int{50, 40, 30}
    
    fmt.Println(len(ourArray))
    
    3
    

    len is a built-in function, not a method. You write len(ourArray), never ourArray.len() or ourArray.length. It returns an int, so you can store it, compare it and use it in arithmetic like any other integer. Go also uses len for strings, maps, channels and arrays. For a string it counts bytes, not characters.

    The length changes with the slice

    Because a slice can grow and shrink, its length is not fixed. Each time you ask, you get the current number of elements:

    ourArray = ourArray[:len(ourArray)-1]
    fmt.Println(len(ourArray))
    
    ourArray = append(ourArray, 7, 8)
    fmt.Println(len(ourArray), ourArray)
    
    2
    4 [50 40 7 8]
    

    Re-slicing to [:len(ourArray)-1] removes the last element, so the length drops from 3 to 2. Appending two values then raises it to 4. Remember to assign the result back to the variable: the length belongs to the new slice value, not to the old one.

    A slice that is empty, including one declared with var s []int that was never filled, has length 0. Calling len on it is always safe.

    Reaching the end of a slice

    The valid indices of a slice with length n run from 0 to n - 1. So the last element is at index len(s) - 1, and the one before it is at len(s) - 2. Many languages let you write s[-1] for the last element. Go does not, so the length is how you reach the end:

    ages := []int{14, 32, 50, 21}
    size := len(ages)
    
    fmt.Println(ages[size-1])
    fmt.Println(ages[size-2])
    
    21
    50
    

    Storing the length in a variable such as size is optional. Writing ages[len(ages)-1] directly is just as common and avoids an extra name. Either way, the length is read at the moment the line runs, so it always matches the slice as it is then.

    The exercise

    You work with two slices:

    fruits := []string{"mango", "kiwi", "grapefruit"}
    ages := []int{14, 32, 50, 21}
    
    1. Print the number of fruits with len(fruits). It is 3.
    2. Print the last age. The slice has four numbers, so the last is at index len(ages) - 1, which is 3.
    3. Print the second to last age at index len(ages) - 2, which is 2.
    fmt.Println(len(fruits))
    fmt.Println(ages[len(ages) - 1])
    fmt.Println(ages[len(ages) - 2])
    
    3
    21
    50
    

    Length and capacity

    A slice also has a capacity, which cap reports. It is the number of elements the underlying array can hold from the start of the slice, so it is never smaller than the length. For a literal the two start out equal. After removing the last element by re-slicing, the length is 2 while the capacity stays 3, because the underlying array is untouched:

    s := []int{50, 40, 30}
    fmt.Println(len(s), cap(s))
    s = s[:len(s)-1]
    fmt.Println(len(s), cap(s))
    
    3 3
    2 3
    

    For the exercises you only need len. Capacity matters later, when you care about how often append has to copy data.

    Looping with the length

    In Go, for is the only loop keyword. Using len in the condition means the loop stays correct when the slice's size changes.

    The length is also the natural limit of a counting loop. This one walks the slice from the end to the start:

    for i := len(ages) - 1; i >= 0; i-- {
    	fmt.Print(ages[i], " ")
    }
    
    21 50 32 14 
    

    Common mistakes

    • Using the length as the last index. ages[len(ages)] is one past the end and panics at run time.
    • Taking the last element of an empty slice. With length 0, the index len(s) - 1 is -1, and the program panics with index out of range [-1]. Test len(s) > 0 first when a slice may be empty.
    • Calling it like a method. ages.len() does not exist; write len(ages).
    • Confusing length and capacity. len counts the elements in the slice. cap reports how many fit in the underlying array before append must allocate a bigger one.

    Key takeaways

    • len(s) is the number of elements, and it changes as the slice grows or shrinks.
    • The last element is s[len(s)-1]; Go has no negative indices.
    • Check for an empty slice before reading from the end.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free