为什么切片a保持不变?是否append()产生一个新的片?
package main
import (
"fmt"
)
var a = make([]int, 7, 8)
func Test(slice []int) {
slice = append(slice, 100)
fmt.Println(slice)
}
func main() {
for i := 0; i < 7; i++ {
a[i] = i
}
Test(a)
fmt.Println(a)
}
Run Code Online (Sandbox Code Playgroud)
输出:
[0 1 2 3 4 5 6 100]
[0 1 2 3 4 5 6]
Run Code Online (Sandbox Code Playgroud)
kos*_*tix 51
在您的示例slice中,Test函数的参数在调用者的范围内接收变量的副本a.
由于切片变量包含仅仅引用基础数组的"切片描述符" ,因此在您的Test函数中,您可以slice连续多次修改变量中保存的切片描述符,但这不会影响调用者及其a变量.
在Test函数内部,第一个append重新分配slice变量下的后备数组,复制其原始内容,附加100到它,这就是你正在观察的内容.退出时Test,slice变量超出范围,切片引用的(新)基础数组也超出范围.
如果你想Test表现得像append,你必须从它返回新的切片 - 就像append那样 - 并要求调用者Test以他们使用的相同方式使用它append:
func Test(slice []int) []int {
slice = append(slice, 100)
fmt.Println(slice)
return slice
}
a = Test(a)
Run Code Online (Sandbox Code Playgroud)
请仔细阅读本文,因为它基本上向您展示了如何append在解释切片如何在内部工作之后手动实现.然后读这个.
Fre*_*Foo 27
典型append用法是
a = append(a, x)
Run Code Online (Sandbox Code Playgroud)
因为append可以就地修改其参数或者使用附加条目返回其参数的副本,具体取决于其输入的大小和容量.使用先前附加的切片可能会产生意外结果,例如
a := []int{1,2,3}
a = append(a, 4)
fmt.Println(a)
append(a[:3], 5)
fmt.Println(a)
Run Code Online (Sandbox Code Playgroud)
可以打印
[1 2 3 4]
[1 2 3 5]
Run Code Online (Sandbox Code Playgroud)
Dav*_*phy 11
为了使您的代码工作而不必从 Test 返回切片,您可以传递这样的指针:
package main
import (
"fmt"
)
var a = make([]int, 7, 8)
func Test(slice *[]int) {
*slice = append(*slice, 100)
fmt.Println(*slice)
}
func main() {
for i := 0; i < 7; i++ {
a[i] = i
}
Test(&a)
fmt.Println(a)
}
Run Code Online (Sandbox Code Playgroud)
注意如果上限不足,追加将生成新切片.@ kostix的答案是正确的,或者你可以通过指针传递切片参数!
试试这个,我认为这一点很清楚.底层数组被更改,但我们的切片不是,print只是打印len()字符,通过另一个切片到cap(),你可以看到更改的数组:
func main() {
for i := 0; i < 7; i++ {
a[i] = i
}
Test(a)
fmt.Println(a) // prints [0..6]
fmt.Println(a[:cap(a)] // prints [0..6,100]
}
Run Code Online (Sandbox Code Playgroud)