在Go中连接两个切片

问题描述 投票:351回答:6

我正在尝试将切片[1, 2]和切片[3, 4]结合起来。我怎么能在Go中这样做?

我试过了:

append([]int{1,2}, []int{3,4})

但得到了:

cannot use []int literal (type []int) as type int in append

然而,the documentation似乎表明这是可能的,我错过了什么?

slice = append(slice, anotherSlice...)
go append slice variadic-functions
6个回答
644
投票

在第二个切片后添加点:

//---------------------------vvv
append([]int{1,2}, []int{3,4}...)

这就像任何其他可变函数一样。

func foo(is ...int) {
    for i := 0; i < len(is); i++ {
        fmt.Println(is[i])
    }
}

func main() {
    foo([]int{9,8,7,6,5}...)
}

64
投票

Appending to and copying slices

可变函数append将零个或多个值x附加到s类型的S,它必须是切片类型,并返回结果切片,也是S类型。值x被传递给...T类型的参数,其中TS的元素类型,并且适用相应的参数传递规则。作为特例,append还接受第一个可赋值给[]byte的参数,第二个参数为string,后跟...。此表单附加字符串的字节。

append(s S, x ...T) S  // T is the element type of S

s0 := []int{0, 0}
s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}

Passing arguments to ... parameters

如果f是具有最终参数类型...T的可变参数,则在函数内该参数等效于类型为[]T的参数。在f的每次调用中,传递给final参数的参数是[]T类型的新切片,其连续元素是实际参数,所有参数都必须可分配给T类型。因此,切片的长度是绑定到最终参数的参数的数量,并且对于每个呼叫站点可以不同。

您的问题的答案是s3 := append(s2, s0...)中的示例Go Programming Language Specification。例如,

s := append([]int{1, 2}, []int{3, 4}...)

26
投票

没有什么可以反对其他答案,但我发现the docs中的简短解释比其中的例子更容易理解:

func追加

func append(slice []Type, elems ...Type) []Type append内置函数将元素附加到切片的末尾。如果它具有足够的容量,则会复制目标以容纳新元素。如果没有,将分配新的底层数组。 Append返回更新的切片。因此有必要存储append的结果,通常在保存切片本身的变量中:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

作为一种特殊情况,将字符串附加到字节切片是合法的,如下所示:

slice = append([]byte("hello "), "world"...)

19
投票

我认为重要的是要指出并知道如果目标切片(您追加的切片)具有足够的容量,则附加将通过重新分配目的地来“就地”发生(重新设置以增加其长度以便成为能够容纳可附加的元素)。

这意味着如果通过切割更大的数组或切片来创建目标,该数组或切片具有超出结果切片长度的其他元素,则它们可能会被覆盖。

要演示,请参阅此示例:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

输出(在Go Playground上试试):

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]

我们创建了一个长度为a的“支持”数组10。然后我们通过切割这个x数组来创建a目标切片,使用复合文字y创建[]int{3, 4}切片。现在当我们将y附加到x时,结果是预期的[1 2 3 4],但可能令人惊讶的是,支持阵列a也发生了变化,因为x的容量是10足以将y附加到它上面,所以x被重置,这将是也使用相同的a支持数组,append()y的元素复制到那里。

如果你想避免这种情况,你可以使用具有该形式的full slice expression

a[low : high : max]

它构造一个切片,并通过将切片的容量设置为max - low来控制切片的容量。

看到修改过的例子(唯一的区别是我们像这样创建xx = a[:2:2]

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

输出(在Go Playground上试试)

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]

正如你所看到的,我们得到相同的x结果,但支持数组a没有改变,因为x的容量是“仅”2(由于完整的切片表达a[:2:2])。因此,要进行追加,会分配一个新的支持数组,它可以存储xy的元素,这与a不同。


4
投票

append()函数和扩展运算符

可以使用标准golang库中的append方法连接两个切片。这类似于variadic功能操作。所以我们需要使用...

package main

import (
    "fmt"
)

func main() {
    x := []int{1, 2, 3}
    y := []int{4, 5, 6}
    z := append([]int{}, append(x, y...)...)
    fmt.Println(z)
}

以上代码的输出为:[1 2 3 4 5 6]


1
投票

append([]int{1,2}, []int{3,4}...)将工作。将参数传递给...参数。

如果f是具有p类型的最终参数...T的可变参数,那么在fp的类型等同于[]T类型。

如果调用f而没有p的实际参数,则传递给p的值是nil

否则,传递的值是[]T类型的新切片,其中包含一个新的基础数组,其连续元素是实际参数,所有这些参数都必须可分配给T。因此,切片的长度和容量是绑定到p的参数的数量,并且对于每个呼叫站点可能不同。

鉴于功能和电话

func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
© www.soinside.com 2019 - 2024. All rights reserved.