在带有扩展运算符的子切片上使用追加是什么意思? [重复]

问题描述 投票:0回答:4

我对以下代码的工作方式感到困惑,尤其是“...”的目的是什么

array = append(array[:i], array[i+1:]...)
go slice
4个回答
2
投票

线

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

通过删除

i
中位置
a
处的项目,通过组合从0到i(不包括)和从i+1到末尾的项目来创建一个新切片。

你的第二个问题是

...
的目的是什么。
append
接受一个切片作为第一个参数,以及无限数量的参数,所有参数的类型都是 assignable 到它的元素的类型。

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 规范在 https://golang.org/ref/spec#Passing_arguments_to_..._parameters:

中所描述的那样

如果 f 是可变的,其最终参数 p 的类型为 ...T,则在 f 中,p 的类型等同于类型 []T。如果调用 f 而 p 没有实际参数,则传递给 p 的值为 nil。否则,传递的值是一个 []T 类型的新切片,带有一个新的底层数组,其连续元素是实际参数,所有这些都必须可分配给 T

游乐场


1
投票
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]

游乐场

在基础

[1,2,3]
中,数据永远不会移动到任何地方,而由
[5,6]
给出的
b[i+1]
被附加到
[1,2,3]
,从而覆盖了
[3,4]
;另一个
[6]
留在原地。

即使您获得切片的不同副本,底层数组也将是相同的*,这使得追加操作比必须复制整个底层数组更有效!

*如果底层数组超出其容量,将分配一个新的更大的数组,并将旧数组中的值复制到新数组,但删除元素时永远不会发生这种情况。


0
投票

Built-in func append 是 Variadic Function.

要将 slice 参数传递给任何可变参数函数,您必须使用

...

Go 语言规范:Passing arguments to ... parameters

如果 f 是可变的,最终参数类型为 ...T,则在 function 参数等同于 []T 类型的参数。在 每次调用 f,传递给最终参数的参数都是一个新的 []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


0
投票

...
的目的是避免您键入单个元素,因为
append
方法将第一个参数作为切片,然后为要附加的元素使用可变数量的参数。

即你实际上需要调用 append as

append(sliceName[:i], array[i+1], array[i+2], array[i+3], array[i+4])

但是为了避免键入一长串元素,您可以在切片或数组之后简单地使用

...
将其作为单个元素展开以作为参数传递。

© www.soinside.com 2019 - 2024. All rights reserved.