关于追加:在go中连接两个slices

Concatenate two slices in Go

我正在尝试组合切片[1, 2]和切片[3, 4]。我该怎么做呢?

我试过:

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

但得到:

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

然而,文档似乎表明这是可能的,我遗漏了什么?

1
slice = append(slice, anotherSlice...)

在第二个切片后添加点:

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

这和其他变量函数一样。

1
2
3
4
5
6
7
8
9
func foo(is ...int) {
    for i := 0; i < len(is); i++ {
        fmt.Println(is[i])
    }
}

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


Appending to and copying slices

The variadic function append appends zero or more values x to s
of type S, which must be a slice type, and returns the resulting
slice, also of type S. The values x are passed to a parameter of
type ...T where T is the element type of S and the respective
parameter passing rules apply. As a special case, append also accepts
a first argument assignable to type []byte with a second argument of
string type followed by .... This form appends the bytes of the
string.

1
2
3
4
5
6
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

If f is variadic with final parameter type ...T, then within the
function the argument is equivalent to a parameter of type []T. At
each call of f, the argument passed to the final parameter is a new
slice of type []T whose successive elements are the actual arguments,
which all must be assignable to the type T. The length of the slice is
therefore the number of arguments bound to the final parameter and may
differ for each call site.

您的问题的答案是go编程语言规范中的示例s3 := append(s2, s0...)。例如,

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


没有什么与其他答案相反,但我发现文档中的简短解释比它们中的示例更容易理解:

func append

func append(slice []Type, elems ...Type) []Type The append built-in
function appends elements to the end of a slice. If it has sufficient
capacity, the destination is resliced to accommodate the new elements.
If it does not, a new underlying array will be allocated. Append
returns the updated slice. It is therefore necessary to store the
result of append, often in the variable holding the slice itself:

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

As a special case, it is legal to append a string to a byte slice,
like this:

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


我认为重要的是要指出并知道,如果目标切片(附加到的切片)有足够的容量,则通过重新单击目标(重新单击以增加其长度,以便能够容纳可附加的元素),附加将"就地"发生。

这意味着,如果目标是通过切片一个更大的数组或切片创建的,而该数组或切片的附加元素超过了结果切片的长度,那么它们可能会被覆盖。

要演示,请参见以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a := [10]int{1, 2}
fmt.Printf("a: %v
", a)

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

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

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

输出(在游乐场上尝试):

1
2
3
4
5
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]

我们创建了一个长度为10的"备份"数组a。然后我们通过切片这个a数组来创建x目的切片,y切片是使用复合文字[]int{3, 4}创建的。现在我们把y附加到x上,结果是预期的[1 2 3 4],但令人惊讶的是,由于x的容量是10足以附加y到它上面,所以x被重新授权使用相同的ab。Acking数组和append()将把y的元素复制到其中。

如果要避免这种情况,可以使用具有

1
a[low : high : max]

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

参见修改后的示例(唯一的区别是我们创建了这样的xx = a[:2:2]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a := [10]int{1, 2}
fmt.Printf("a: %v
", a)

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

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

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

输出(在游乐场上尝试)

1
2
3
4
5
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不同。


append()函数和spread运算符

在标准的Golang库中,可以使用append方法连接两个切片。类似于variadic功能操作。所以我们需要使用EDOCX1[30]

1
2
3
4
5
6
7
8
9
10
11
12
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)
}

output of the above code is: [1 2 3 4 5 6]


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

如果f...T型的最终参数p是变量,那么在f内,p型相当于[]T型。

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

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

给定函数和调用

1
2
3
func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:","Joe","Anna","Eileen")