我试图将切片[1,2]和切片[3,4]结合起来。我如何在围棋中做到这一点?
我试着:
append([]int{1,2}, []int{3,4})
但有:
cannot use []int literal (type []int) as type int in append
然而,文档似乎表明这是可能的,我错过了什么?
slice = append(slice, anotherSlice...)
我试图将切片[1,2]和切片[3,4]结合起来。我如何在围棋中做到这一点?
我试着:
append([]int{1,2}, []int{3,4})
但有:
cannot use []int literal (type []int) as type int in append
然而,文档似乎表明这是可能的,我错过了什么?
slice = append(slice, anotherSlice...)
当前回答
Append()函数和展开运算符
可以使用标准golang库中的append方法连接两个片。这类似于变进函数的运算。所以我们需要用…
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]
其他回答
要连接两个切片,
func main() {
s1 := []int{1, 2, 3}
s2 := []int{99, 100}
s1 = append(s1, s2...)
fmt.Println(s1) // [1 2 3 99 100]
}
将单个值附加到片
func main() {
s1 := []int{1,2,3}
s1 := append(s1, 4)
fmt.Println(s1) // [1 2 3 4]
}
将多个值追加到一个片
func main() {
s1 := []int{1,2,3}
s1 = append(s1, 4, 5)
fmt.Println(s1) // [1 2 3 4]
}
我想强调@icza的答案,并简化一下,因为它是一个至关重要的概念。我假设读者对切片很熟悉。
c := append(a, b...)
这是对这个问题的有效回答。 但是,如果你需要在以后的代码中在不同的上下文中使用切片'a'和'c',这不是连接切片的安全方法。
为了解释,让我们不从切片的角度来阅读表达式,而是从底层数组的角度来阅读:
取(底层的)数组'a',并将数组'b'中的元素附加到 它。如果数组'a'有足够的容量包含'b'中的所有元素 c的底层数组不会是一个新数组,它实际上是数组a。基本上,切片'a'将显示len(a)个元素 底层数组a和切片c将显示数组a的len(c) "
Append()不一定创建一个新数组!这可能会导致意想不到的结果。参见Go Playground的例子。
如果你想确保新数组被分配给切片,总是使用make()函数。例如,这里有一些丑陋但足够有效的任务选项。
la := len(a)
c := make([]int, la, la + len(b))
_ = copy(c, a)
c = append(c, b...)
la := len(a)
c := make([]int, la + len(b))
_ = copy(c, a)
_ = copy(c[la:], b)
似乎是泛型的完美用途(如果使用1.18或更高版本)。
func concat[T any](first []T, second []T) []T {
n := len(first);
return append(first[:n:n], second...);
}
我认为重要的是要指出并知道,如果目标片(你追加的片)有足够的容量,追加将“原地”发生,通过重切片目的地(重切片增加它的长度,以便能够容纳可追加的元素)。
这意味着如果目标是通过切片一个更大的数组或切片创建的,其中有超出结果切片长度的额外元素,它们可能会被覆盖。
为了演示,请看这个例子:
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]
我们创建了一个长度为10的“支持”数组a。然后我们通过将这个数组切片来创建x目标切片,y切片使用复合文字[]int{3,4}创建。现在,当我们将y追加到x时,结果是预期的[1 2 3 4],但可能令人惊讶的是,后备数组a也发生了变化,因为x的容量为10,这足以将y追加到它,因此x被重新分割,这也将使用相同的后备数组,append()将复制y的元素到那里。
如果你想避免这种情况,你可以使用一个完整的切片表达式
a[low : high : max]
它构造一个切片,并通过将其设置为Max - low来控制结果切片的容量。
查看修改后的示例(唯一的区别是我们像这样创建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 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])。为了追加,分配了一个新的后备数组它可以存储x和y的元素,这与a是不同的。
Append()函数和展开运算符
可以使用标准golang库中的append方法连接两个片。这类似于变进函数的运算。所以我们需要用…
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]