golang都是值传递,为什么在函数内修改切片的元素还能反应到外部?

func exampleFunc(arr []int) {
    arr[0] = 100
    arr[1] = 101
    
    arr = append(arr, 111)
}
func main() {
    //创建一个int slice
    arr := make([]int, 2, 5)
    //给切片添加元素
    for i := 0; i < len(arr); i++ {
        arr[i] = i
    }
    //把arr作为参数传递到exampleFunc函数中
    exampleFunc(arr)
    //遍历arr
    for i := 0; i <len(arr); i++ {
        fmt.Printf("%d\n",arr[i]) //输出100 101
    }
}

为什么在函数内通过索引可以改切片的元素,append函数却不行?

阅读 2.1k
1 个回答

slice 是值传递。

但是,slice 有一个 underlying array ,并不是 slice 的一部分,而只是一个引用。就是说,拷贝 slice 得到一个新的 slice ,但是他们共享了同一个underlying array 。通过下标修改内容,直接修改了 underlying array 里的内容,所以外部可见。

append 会向 slice 中添加值,这就带来一个问题,就是 underlying array 可能空间不够了。这个时候就,append 返回的 slice 会使用一个新的(更大的)underlying array 。于是返回的 slice 与输入的 slice 就不再共享同一个 underlying array 。
同时,append 没有修改输入的 slice,而是返回一个新 slice ,返回的 slice 与输入的 slice 长度也是不同的。

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