How to get the last element of a slice?

GoSlice

Go Problem Overview


What is the Go way for extracting the last element of a slice?

var slice []int

slice = append(slice, 2)
slice = append(slice, 7)

slice[len(slice)-1:][0] // Retrieves the last element

The solution above works, but seems awkward.

Go Solutions


Solution 1 - Go

For just reading the last element of a slice:

sl[len(sl)-1]

For removing it:

sl = sl[:len(sl)-1]

See this page about slice tricks

Solution 2 - Go

You can use the len(arr) function, although it will return the length of the slice starting from 1, and as Go arrays/slices start from index 0 the last element is effectively len(arr)-1

Example:

arr := []int{1,2,3,4,5,6} // 6 elements, last element at index 5
fmt.Println(len(arr)) // 6
fmt.Println(len(arr)-1) // 5
fmt.Println(arr[len(arr)-1]) // 6 <- element at index 5 (last element)

Solution 3 - Go

If you can use Go 1.18 or above and you often need to access the last element of a slice of some arbitrary element type, the use of a small custom function can improve readability at call sites:

package main

import "fmt"

func Last[E any](s []E) (E, bool) {
	if len(s) == 0 {
		var zero E
		return zero, false
	}
	return s[len(s)-1], true
}

func main() {
	var numbers []int
	fmt.Println(Last(numbers)) // 0 false
	numbers = []int{4, 8, 15, 16, 23, 42}
	fmt.Println(Last(numbers)) // 42 true
}

(Playground)

No need to create a library for that Last function, though; a little copying is better than a little dependency.

Solution 4 - Go

What is even more awkward is your program crashing on empty slices!

To contend with empty slices -- zero length causing panic: runtime error, you could have an if/then/else sequence, or you can use a temporary slice to solve the problem.

package main

import (
	"fmt"
)

func main() {
	// test when slice is not empty
    itemsTest1 := []string{"apple", "grape", "orange", "peach", "mango"}

    tmpitems := append([]string{"none"},itemsTest1...)
    lastitem := tmpitems[len(tmpitems)-1]
    fmt.Printf("lastitem: %v\n", lastitem)

    // test when slice is empty
    itemsTest2 := []string{}

    tmpitems = append([]string{"none"},itemsTest2...) // <--- put a "default" first
    lastitem = tmpitems[len(tmpitems)-1]
    fmt.Printf("lastitem: %v\n", lastitem)
}

which will give you this output:

lastitem: mango
lastitem: none

For []int slices you might want a -1 or 0 for the default value.

Thinking at a higher level, if your slice always carries a default value then the "tmp" slice can be eliminated.

Solution 5 - Go

Bit less elegant but can also do:

sl[len(sl)-1: len(sl)]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMorgan WildeView Question on Stackoverflow
Solution 1 - GoToni CárdenasView Answer on Stackoverflow
Solution 2 - GoleonardoView Answer on Stackoverflow
Solution 3 - Gojub0bsView Answer on Stackoverflow
Solution 4 - GowarrensView Answer on Stackoverflow
Solution 5 - GoccdrmView Answer on Stackoverflow