将引用类型“slice”的变量分配给另一个变量,为什么它们不能同时更改?

时间:2016-04-27 13:12:23

标签: go reference-type

anotherSlice := theSlice
anotherSlice = append(anotherSlice, newEle)
fmt.Println(len(anotherSlice) == len(theSlice))

此代码段将输出false。为什么呢?

以下是其他一些实验:

package main

import "fmt"

func main() {
    theSlice := []int{3,3,2,5,12,43}
    anotherSlice := theSlice
    fmt.Println(anotherSlice[3], theSlice[3])
    anotherSlice[3] = anotherSlice[3]+2
    fmt.Println(anotherSlice[3], theSlice[3])
    anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...)
    fmt.Println(len(anotherSlice),len(theSlice))
}

输出如下:

5 5
7 7
5 6

Program exited.

2 个答案:

答案 0 :(得分:2)

每当附加切片anotherSlice没有新元素的容量时,append函数会创建新切片并返回它。从那时起,切片anotherSlicetheSlice就不同了 - 它们由不同的数组支持。

重新切割长度较短的切片anotherSlice[:3]不会影响切片的原始容量。

以下一行:

anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...)

削减第四(索引3)元素。由于anotherSlice[:3]具有容纳anotherSlice[4:]的所有元素的容量,因此不会发生新的分配,因此两个切片都会被修改。

package main

import (
        "fmt"
)   

func main() {
        x := []int{1, 2, 3, 4, 5, 6}
        fmt.Println(cap(x[:3]) >= len(x[:3])+len(x[4:]))
        y := append(x[:3], x[4:]...)
        fmt.Println(x, y)
}

Playground

答案 1 :(得分:1)

为什么一个切片的长度不会跟随另一个切片长度变化的变化的原因与可能被复制和/或修改的底层存储无关。

在Go中,记住切片是很重要的。它是一个带有长度字段,容量字段和指向数组的指针的结构。一些操作 改变长度字段。有些人改变了容量字段。有些更改存储在基础数组中的数据。

如果没有人掌握语言中切片的实现方式,就会出现各种混乱,错误和浪费的机会。一旦人们对切片的实现方式感到满意,它们就非常易于使用,并且编译器能够理解切片的结构,可以编写一些非常优雅且易于读取的代码。