ChatGPT解决这个技术问题 Extra ChatGPT

How to get the last element of a slice?

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.


B
Benjamin W.

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


Thanks a bunch! Even though it does seem silly they didn't add the -1 index Python has...
I do like the -1 from Python, although it often lead to hard-to-debug errors.
They left it outside consciously. It was non-obvious and prone to errors. Go overall is circumspect about 'too much meaning'; it also doesn't feature method/operator overloading, default values for function params, etc. which IMHO goes in a similar philosophical vein. See this discussion and others: groups.google.com/forum/#!topic/golang-nuts/yn9Q6HhgWi0
I am not sure but I got panic: runtime error: index out of range for profiles[len(profiles)-1].UserId, I guess the length of the slice is 0 so it panics?
@tom10271 Yes, you can't get the last element of a slice if there's no such element, ie. if there are no elements at all.
j
jub0bs

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.


and now there's a proposal to add that to x/exp/slices
l
leonardo

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)

w
warrens

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.