Go语言 在子切片上使用spread操作符的append是什么意思?[副本]

dm7nw8vv  于 2023-05-20  发布在  Go
关注(0)|答案(4)|浏览(156)

此问题已在此处有答案

How to delete an element from a Slice in Golang(21个回答)
What does ... mean when coming directly after a slice?(2个答案)
4天前关闭。
我对下面的代码是如何工作的感到困惑,尤其是“…”的目的是什么

array = append(array[:i], array[i+1:]...)
nwlqm0z1

nwlqm0z11#

那条线

a = append(a[:i], a[i+1:]...)

通过删除a中位置i处的项、通过组合从0到i(不包括)以及从i+1到末尾的项来创建新切片。
第二个问题是...的用途是什么。append接受一个切片作为第一个参数,以及无限数量的参数,所有参数都具有可分配给其元素类型的类型。
append定义为

func append(slice []Type, elems ...Type) []Type

写作

a = append(a[:i], a[i+1:]...)

等同于书写

a = append(a[:i], a[i+1], a[i+2], a[i+3], a[i+4]) //and so on, until the end of the slice.

使用a[i+1:]...基本上是一种速记语法,正如Go规范在www.example.com中所描述的https://golang.org/ref/spec#Passing_arguments_to_..._parameters:
如果f是变元函数,其最终参数p的类型为...T,则在f中p的类型等价于类型[]T。如果调用f时没有p的实际参数,则传递给p的值为nil。否则,传递的值是一个类型为[]T的新切片,它带有一个新的底层数组,该数组的后续元素是实际参数,这些参数都必须可赋给T
Playground

mnemlml8

mnemlml82#

array = append(array[:i], array[i+1:]...)

删除索引为i的元素
但需要指出的另一件事是,slice由底层数组支持。例如:

package main

import (
    "fmt"
)

func main() {
    myArray := [6]int {1,2,3,4,5,6}

    mySlice := myArray[:]

    fmt.Println("myArray before append: ", myArray)

    i := 3
    mySlice = append(mySlice[:i], mySlice[i+1:]...)

    fmt.Println("mySlice after append: ", mySlice)
    fmt.Println("myArray after append: ", myArray)
}

结果:

myArray before append:  [1 2 3 4 5 6]
mySlice after append:  [1 2 3 5 6]
myArray after append:  [1 2 3 5 6 6]

goplayground
在底层的[1,2,3]中,数据永远不会移动到任何地方,而由b[i+1]给出的[5,6]被附加到[1,2,3],从而覆盖了[3,4];另一个[6]留在原地。
即使你得到了不同的切片副本,底层数组也是相同的 *,这使得append操作比复制整个底层数组更有效!

  • 如果底层数组超出了它的容量,将分配一个新的更大的数组,旧数组中的值将被复制到新数组中,但在删除元素时不会发生这种情况。
qpgpyjmq

qpgpyjmq3#

内置函数append是Variadic函数。
要将slice参数传递给任何可变参数函数,必须使用...
Go lang规格:将参数传递给...参数
如果f是final参数类型为...T的变元函数,则在函数内部,参数等价于类型为[]T的参数。在每次调用f时,传递给final参数的参数是一个类型为[]T的新切片,其后续元素是实际参数,所有这些参数都必须可分配给类型T。因此,切片的长度是绑定到最终参数的参数的数量,并且对于每个调用位置可能不同。
这一行将给予一个删除位置i的结果值。

array = append(array[:i], array[i+1:]...)

假设我们有

array := []int{1, 2, 3, 4, 5, 6, 7}
i := 3

fmt.Println("Original slice:", array)

part1 := array[:i]
part2 := array[i+1:]
fmt.Println("part1:", part1)
fmt.Println("part2:", part2)

array = append(array[:i], array[i+1:]...)
fmt.Println("Result slice:", array)

输出:

Original slice: [1 2 3 4 5 6 7]
part1: [1 2 3]
part2: [5 6 7]
Result slice: [1 2 3 5 6 7]

播放链接:https://play.golang.org/p/_cIk0VcD6w

xqkwcwgp

xqkwcwgp4#

...的目的是保存您输入单个元素,因为append方法将第一个参数作为切片,然后为要追加的元素提供可变数量的参数。
也就是说,实际上需要调用append as
append(sliceName[:i], array[i+1], array[i+2], array[i+3], array[i+4])
但是为了避免输入一长串的元素,你可以简单地在切片或数组后面使用...,将其作为单独的元素作为参数传递。

相关问题