3 回答
TA贡献1780条经验 获得超4个赞
在您的示例slice
中,Test
函数的参数接收调用者作用域中变量的副本a
。
由于切片变量包含一个仅引用底层数组的“切片描述符” ,因此在您的Test
函数中,您可以slice
连续多次修改保存在变量中的切片描述符,但这不会影响调用者及其a
变量。
在Test函数外部,分配了一个长度为 7 和容量为 8 的切片,并填充了它的 7 个元素。
在Test函数内部,第一个append看到切片的容量仍然比它的长度大一个元素——换句话说,还有一个空间可以添加一个元素而无需重新分配。所以它“吃掉”剩余的元素并将其放置100到它上面,然后它调整切片描述符副本中的长度,使其等于切片的容量。这不会影响调用者范围内的切片描述符。
这就是你正在观察的。从 退出时Test,slice变量超出范围,切片引用的(新)底层数组也超出范围。
如果你想让Test行为像append,你必须从中返回新的切片——就像 doappend一样——并要求 的调用者以Test与使用相同的方式使用它append:
func Test(slice []int) []int {
slice = append(slice, 100)
fmt.Println(slice)
return slice
}
a = Test(a)
TA贡献1772条经验 获得超8个赞
典型append用法是
a = append(a, x)
因为append可以就地修改其参数或返回其参数的副本以及附加条目,具体取决于其输入的大小和容量。使用先前附加到的切片可能会产生意想不到的结果,例如
a := []int{1,2,3}
a = append(a, 4)
fmt.Println(a)
append(a[:3], 5)
fmt.Println(a)
可以打印
[1 2 3 4]
[1 2 3 5]
TA贡献2036条经验 获得超8个赞
为了使您的代码工作而不必从 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)
}
- 3 回答
- 0 关注
- 234 浏览
添加回答
举报