在Go中连接两个切片
我试图把切片[1, 2]
和切片[3, 4]
[1, 2]
结合起来。 我怎么在Go上做这个?
我试过了:
append([]int{1,2}, []int{3,4})
但得到:
cannot use []int literal (type []int) as type int in append
但是, 文件似乎表明这是可能的,我错过了什么?
slice = append(slice, anotherSlice...)
在第二个切片之后添加点:
//---------------------------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}...) }
追加和复制切片
可变参数函数
append
将零或多个值x
附加到s
types的S
,它必须是一个分片types,并返回S
types的结果分片。 值x
被传递给types为...T
的参数,其中T
是S
的元素types,并且相应的parameter passing规则适用。 作为一种特殊情况,append还接受第一个可分配types为[]byte
的参数,第二个参数为string
types,后跟...
这个表单附加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}
将parameter passing给…参数
如果
f
是最终参数types...T
可变参数,那么在该函数内参数相当于[]T
的参数。 在f
每次调用中,传递给最终参数的参数都是一个新types的连续元素[]T
,它们的连续元素是实际参数,它们都必须是可分配给typesT
。 切片的长度因此是绑定到最终参数的参数的数量,并且对于每个调用位置可能不同。
你的问题的答案是在Go Programming Language Specification中的例子s3 := append(s2, s0...)
。 例如,
s := append([]int{1, 2}, []int{3, 4}...)
没有任何反对其他答案,但我发现在文档中的简单解释比其中的例子更容易理解:
func追加
func append(slice []Type, elems ...Type) []Type
追加内置函数将元素追加到切片的末尾。 如果它有足够的容量,目的地将被重新调整以适应新的元素。 如果没有,将分配一个新的底层数组。 追加返回更新的切片。 因此,需要将追加的结果存储在保存片本身的variables中:slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...)
作为一种特殊情况,将string追加到字节片是合法的,如下所示:
slice = append([]byte("hello "), "world"...)
我认为重要的是要指出并知道,如果目标片(您附加的片)具有足够的容量,那么追加将通过复制目的地(重复增加其长度)“就地”发生。
这意味着如果通过对具有超出所得分片长度的附加元素的较大数组或切片进行切片来创build目标,则它们可能会被覆盖。
为了演示,请看这个例子:
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]
我们创build了a
长度为10
的“后备”数组a
。 然后我们通过对这个数组进行切片来创buildx
目标切片,使用复合文字[]int{3, 4}
创buildy
切片。 现在,当我们将y
附加到x
,结果是预期的[1 2 3 4]
,但是令人惊讶的是,支持数组a
也发生了变化,因为x
容量是10
,足以将y
附加到它,所以x
是resliced这也将使用相同a
支持数组,而append()
会将y
元素复制到那里。
如果你想避免这种情况,你可以使用一个完整的expression式
a[low : high : max]
它构build一个切片,并通过将切片的容量设置为max - low
来控制切片的容量。
看到修改的例子(唯一的区别是我们创build这样的x
: x = 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游乐场尝试)
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
(感谢完整的片段expression式a[:2:2]
)。 所以要做append,一个新的backing数组被分配,可以存储x
和y
的元素,这与y
不同。