Question

How to Get the Last Element of a Slice in Go

goslice

Question

In Go, what is the idiomatic way to retrieve the last element of a slice?

var slice []int

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

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

The code above works, but it feels awkward. Is there a cleaner and more idiomatic way to get the last item from a slice?

Short Answer

By the end of this page, you will understand how to access the last element of a slice in Go, why direct indexing is the usual approach, how to handle empty slices safely, and which slice expressions are unnecessary for this task.

Concept

In Go, a slice is a lightweight view over an underlying array. To access an element in a slice, you normally use its index.

Because Go slices are zero-indexed:

  • The first element is at index 0
  • The second element is at index 1
  • The last element is at index len(slice) - 1

So the idiomatic way to get the last element is:

last := slice[len(slice)-1]

This works because len(slice) gives the number of elements, and the final valid index is always one less than that count.

Your original code:

slice[len(slice)-1:][0]

first creates a new slice containing the last element, then indexes into that new slice to get the element back. It is valid, but unnecessary.

Why this matters in real programs:

  • Slices are used everywhere in Go: API data, file lines, query results, queues, stacks, and more.
  • Accessing the last element is common when processing sequences.
  • Writing the simplest correct form makes code easier to read and maintain.

One important rule: if the slice is empty, slice[len(slice)-1] will panic because there is no last element.

Mental Model

Think of a slice like a row of numbered boxes.

If there are 5 boxes, their positions are:

  • 0
  • 1
  • 2
  • 3
  • 4

The total count is 5, but the last box is at position 4, which is 5 - 1.

So len(slice) tells you how many boxes exist, and len(slice)-1 tells you where the last box is.

Your original approach is like taking the last box, putting it into a tiny one-box tray, and then opening that tray to take it out again. It works, but it adds an extra step.

Take Quiz

Syntax and Examples

The standard syntax is:

last := slice[len(slice)-1]

Example with integers

package main

import "fmt"

func main() {
    nums := []int{2, 7, 10}
    last := nums[len(nums)-1]
    fmt.Println(last)
}

Output:

10

Example with strings

package main

import "fmt"

func main() {
    names := []string{"Ana", "Ben", "Cara"}
    fmt.Println(names[len(names)-1])
}

Output:

Cara

Safe version for possibly empty slices

package main

import "fmt"

func main() {
    nums := []int{}

    if len(nums) == 0 {
        fmt.Println("slice is empty")
        return
    }

    fmt.Println(nums[len(nums)-1])
}

This check is important when you are not sure whether the slice contains any elements.

Step by Step Execution

Consider this code:

package main

import "fmt"

func main() {
    nums := []int{2, 7, 11}
    last := nums[len(nums)-1]
    fmt.Println(last)
}

Step by step:

  1. nums := []int{2, 7, 11} creates a slice with 3 elements.
  2. len(nums) returns 3.
  3. len(nums) - 1 becomes 2.
  4. nums[2] accesses the element at index 2.
  5. That element is 11.
  6. last is assigned the value 11.
  7. fmt.Println(last) prints 11.

Visual trace

nums = [2 7 11]
index  0 1 2
len(nums) = 3
last index = 3 - 1 = 2
nums[2] = 11

What happens if the slice is empty?

nums := []int{}
fmt.Println(nums[len(nums)-1])

Step by step:

  1. len(nums) returns 0.
  2. len(nums) - 1 becomes -1.
  3. Go tries to access nums[-1].
  4. That is invalid.
  5. The program panics with an index out of range error.

Real World Use Cases

Getting the last element of a slice appears in many practical situations:

  • Log processing: get the most recent log entry.
  • Web APIs: read the last item returned by a paginated response.
  • Command history: get the most recent command.
  • Stack-like behavior: inspect the top item before popping it.
  • Data pipelines: compare the newest value with the previous ones.
  • File parsing: get the last line after splitting content.

Example: latest event in a list

events := []string{"created", "updated", "deleted"}
latest := events[len(events)-1]

Example: stack top

stack := []int{10, 20, 30}
top := stack[len(stack)-1]

These patterns are simple, direct, and common in Go programs.

Take Quiz

Real Codebase Usage

In real Go codebases, developers usually pair direct indexing with small safety checks.

Common pattern: guard clause

if len(items) == 0 {
    return errors.New("no items available")
}

last := items[len(items)-1]

This is readable and prevents panics.

Common pattern: helper function

If your code often needs the last element, you may wrap the logic:

func lastInt(nums []int) (int, bool) {
    if len(nums) == 0 {
        return 0, false
    }
    return nums[len(nums)-1], true
}

This makes callers handle the empty case explicitly.

Common pattern: stack operations

func peek(stack []string) (string, bool) {
    if len(stack) == 0 {
        return "", false
    }
    return stack[len(stack)-1], true
}

Why developers usually avoid slice[len(slice)-1:][0]

  • It is harder to read.
  • It suggests slicing is needed when it is not.
  • It does extra work conceptually for the same result.
  • It hides the main idea: direct access by index.

In production code, clarity usually wins.

Common Mistakes

1. Forgetting to handle empty slices

Broken code:

nums := []int{}
last := nums[len(nums)-1]

This panics.

Better:

if len(nums) == 0 {
    fmt.Println("empty slice")
    return
}
last := nums[len(nums)-1]

2. Using len(slice) as the last index

Broken code:

nums := []int{2, 7, 11}
fmt.Println(nums[len(nums)])

Why it fails:

  • len(nums) is 3
  • Valid indexes are 0, 1, and 2

Correct version:

fmt.Println(nums[len(nums)-1])

3. Using an unnecessary slice expression

Less clear:

last := nums[len(nums)-1:][0]

Cleaner:

last := nums[len(nums)-1]

4. Confusing slices with arrays

Arrays and slices are related, but not the same. The syntax for indexing is similar, but slices are more commonly used in Go because they are flexible and can grow.

5. Assuming negative indexes work

Some languages allow negative indexing like arr[-1] for the last element. Go does not.

Invalid in Go:

nums[-1]

Use:

nums[len(nums)-1]

Comparisons

ApproachExampleWorks?Idiomatic?Notes
Direct indexingslice[len(slice)-1]YesYesStandard way to get the last element
Slice then indexslice[len(slice)-1:][0]YesNoUnnecessary extra step
Using len(slice) directlyslice[len(slice)]NoNoPanics: out of range
Negative indexslice[-1]NoNoGo does not support negative indexes

Slice expression vs index expression

slice[a:b] // returns a new slice
slice[i]   // returns a single element

If you want one element, use indexing.

If you want a sub-slice, use slicing.

Arrays vs slices

FeatureArraySlice
SizeFixedDynamic view over an array
Common in Go codeLess commonVery common
Last element accessarr[len(arr)-1]slice[len(slice)-1]

The last-element logic is the same for both.

Take Quiz

Cheat Sheet

// Get last element
last := slice[len(slice)-1]

// Safe check
if len(slice) == 0 {
    // handle empty slice
}

// Last index
lastIndex := len(slice) - 1

Rules

  • Go slices are zero-indexed.
  • The last valid index is always len(slice) - 1.
  • Accessing an invalid index causes a panic.
  • Go does not support negative indexes.
  • Use indexing for one element, not slicing.

Common safe pattern

if len(slice) > 0 {
    last := slice[len(slice)-1]
    fmt.Println(last)
}

Avoid

slice[len(slice)]     // out of range
slice[-1]             // invalid in Go
slice[len(slice)-1:][0] // works, but unnecessary

FAQ

What is the idiomatic way to get the last element of a slice in Go?

Use direct indexing:

last := slice[len(slice)-1]

Why is slice[len(slice)-1:][0] considered awkward?

Because it creates a one-element sub-slice and then indexes into it. It is more complicated than needed when you only want one value.

What happens if the slice is empty?

Your program will panic with an index out of range error. Always check len(slice) == 0 if the slice might be empty.

Does Go support negative indexing like slice[-1]?

No. Go does not allow negative indexes.

Can I use the same approach with a string slice or struct slice?

Yes. The pattern works with any slice type:

lastName := names[len(names)-1]

Is this the same for arrays in Go?

Yes. Arrays also use zero-based indexing, so the last element is at len(arr)-1.

Should I write a helper function for this?

If you need this often or want safer code, a helper that returns (value, ok) can be a good idea.

Take Quiz

Mini Project

Description

Build a small Go program that stores recent scores in a slice and prints the latest score. This demonstrates how to get the last element of a slice safely, which is a common need when working with recent activity, logs, history lists, or stack-like data.

Goal

Create a program that appends several scores, prints the last score, and safely handles the case where no scores exist.

Requirements

  • Create a slice of integers to hold scores.
  • Append at least three scores to the slice.
  • Print the last score using idiomatic slice indexing.
  • Add a safety check for the empty-slice case.
  • Show a second example with an empty slice.
Take Quiz

Keep learning

Related questions

View more