Golang 将项目附加到切片

新手上路,请多包涵

为什么切片 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)
}

输出:

 [0 1 2 3 4 5 6 100]
[0 1 2 3 4 5 6]

原文由 Pole_Zhang 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 620
1 个回答

在您的示例中, Test 函数的 slice 参数在调用方的范围内接收变量 a _的副本_。

由于切片变量包含仅 引用 底层数组的“切片描述符”,因此在您的 Test 函数中,您连续多次修改 slice 变量中保存的切片描述符,但是这不会影响调用者及其 a 变量。

Inside the Test function, the first append reallocates the backing array under the slice variable, copies its original contents over, 100 to它,这就是你正在观察的。从 Test 退出后, slice 变量超出范围,切片引用的(新)底层数组也超出范围。 ( 杰夫李 是正确的,这不是真正发生的事情,所以更新版本如下;正如他正确指出的那样, 这个答案 是正确的,如果可能有点过于简洁。)

Test 函数之外,分配了一个长度为7,容量为8的slice,并填充了它的7个元素。

Test 函数中,第一个 append 看到切片的容量仍然比它的长度大一个元素——换句话说,有空间可以再添加一个元素而无需重新分配.所以它“吃掉”剩余的元素并将 100 到它,之后它调整切片描述符副本中的长度,使其等于切片的容量。这不会影响调用者范围内的切片描述符。

这就是你正在观察的。从 Test 退出后, slice 变量超出范围,切片引用的(新)底层数组也超出范围。

如果你想让 Test 表现得像 append , _你必须从它返回新的切片_——就像 append -4bd8- 的调用者需要 Test 以相同的方式使用它 append

 func Test(slice []int) []int {
    slice = append(slice, 100)

    fmt.Println(slice)

    return slice
}

a = Test(a)

请仔细阅读 这篇文章,因为它基本上向您展示了如何在解释了切片的内部工作原理之后如何手动实现 append 。然后读 这个

原文由 kostix 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏