ChatGPT解决这个技术问题 Extra ChatGPT

如何获取切片的最后一个元素?

提取切片的最后一个元素的 Go 方法是什么?

var slice []int

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

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

上面的解决方案有效,但似乎很尴尬。


B
Benjamin W.

仅读取切片的最后一个元素:

sl[len(sl)-1]

删除它:

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

看到这个page about slice tricks


非常感谢!尽管看起来确实很愚蠢,但他们没有添加 Python 具有的 -1 索引...
我确实喜欢 Python 中的 -1,尽管它经常导致难以调试的错误。
他们有意识地把它留在外面。这是不明显的并且容易出错。总体而言,对“太多意义”是谨慎的;它也没有方法/运算符重载、函数参数的默认值等,恕我直言,这些都是类似的哲学思想。请参阅此讨论和其他讨论:groups.google.com/forum/#!topic/golang-nuts/yn9Q6HhgWi0
我不确定,但我得到了 profiles[len(profiles)-1].UserIdpanic: runtime error: index out of range,我猜切片的长度是 0,所以它会恐慌吗?
@ tom10271 是的,如果没有这样的元素,您将无法获取切片的最后一个元素,即。如果根本没有元素。
j
jub0bs

如果您可以使用 Go 1.18 或更高版本,并且您经常需要访问某个任意元素类型切片的最后一个元素,则使用一个小的自定义函数可以提高调用站点的可读性:

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)

不过,无需为该 Last 函数创建库; a little copying is better than a little dependency


现在有 a proposal 将其添加到 x/exp/slices
l
leonardo

您可以使用 len(arr) 函数,尽管它会返回从 1 开始的切片长度,并且由于 Go 数组/切片从索引 0 开始,最后一个元素实际上是 len(arr)-1

例子:

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

更尴尬的是您的程序在空切片上崩溃!

为了应对空切片——零长度导致 panic: runtime error,您可以使用 if/then/else 序列,或者您可以使用临时切片来解决问题。

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)
}

这将为您提供以下输出:

lastitem: mango
lastitem: none

对于 []int 切片,您可能需要 -10 作为默认值。

从更高的层面思考,如果您的切片始终带有默认值,则可以消除“tmp”切片。