正确理解golang slice的复制

栏目: Go · 发布时间: 5年前

内容简介:golang 的slice是一个指向底层的数组的指针结构体。 这个结构体有三个属性,1.指向数组指针,2.len: slice中元素的数量 3.cap:slice占用内存数量。 只有深刻理解这三个属性才能在使用slice中不至于犯错。多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠以上是golang 圣经中的一句话。深刻理解这句话对于日程编程非常有意义。

slice 三个属性

golang 的slice是一个指向底层的数组的指针结构体。 这个结构体有三个属性,1.指向数组指针,2.len: slice中元素的数量 3.cap:slice占用内存数量。 只有深刻理解这三个属性才能在使用slice中不至于犯错。

正确理解变量和共享

多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠

以上是golang 圣经中的一句话。深刻理解这句话对于日程编程非常有意义。

1.什么时候共享数据会被其他变量修改

func f1()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]

    a1[1] = 999
    
    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

运行结果

a1= [1 999 3 4 5 6] a2= [1 999 3 4 5 6] a3= [999 3]

Process finished with exit code 0

我们清楚的看到了数据共享,此时修改了a1 ,两位两个变量都被修改

什么时候不会修改

func f2()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]

    a2 = append(a2,888)

    a1[1] = 999

    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

运行结果

a1= [1 999 3 4 5 6] a2= [1 2 3 4 5 6 888] a3= [999 3]

Process finished with exit code 0

可以虽然a1被修改,a2并没有修改。我们知道append函数会面临内存的重新分配。所以等a2进行append的时候,会重新申请内存空间,将原有数组拷贝然后增加如新值。也就是当append操作的时候,此时a2 不在和a1 共享内存了。所以后续对a1的操作是不会影响到a2.

3.所有的append操作都会隔断内存共享?

func f3()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]
    a2 = append(a2,888)
    a3 = append(a3,777)

    a1[1] = 999

    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

运行结果

a1= [1 999 3 777 5 6] a2= [1 2 3 4 5 6 888] a3= [999 3 777]

Process finished with exit code 0

这次a3 是对a1进行切片操作赋值的新变量。此时对a3进行append操作,我们发现a1的值同步被修改了。所以此时a3 和a1 仍然是共享内存,append并没有申请新的内存空间而是继续在a3的数据末尾写入,这样对于a1 是覆盖了原有值。

问题本质是

a1= [1 999 3 777 5 6] cap(a1) =  6  a2= [1 2 3 4 5 6 888] cap(a2) =  12  a3= [999 3 777] cap(a3) =  5

重新运行后将三个变量cap值打印为以上输出。

问题的本质是len 和cap 的值。 在slice中,当len小于cap 的值的时候, 进行append 操作是不会造成内存的重新分配。a3 是从a1切片操作而来,我们看到a3 初始化的len =2 ,cap =5.所以在append中不会引起内存重新分配,go 运行时会继续将数据依次写入。这样就修改了a3 和a1共享的内存空间。 对于a2,在初始化的时候len =cap =6. 在append操作的时候就会重新申请空间,go会分配当前空间 * 2 的内存。所以append后的cap就是12 如上。

总结

在对slice 复制的时候,如果面临多个变量同时指向一个数组的时候,一定要考虑到数据的共享和内存的重新分配。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

像程序员一样思考

像程序员一样思考

V. Anton Spraul / 徐波 / 人民邮电出版社 / 2013-6 / 49.00元

编程的真正挑战不是学习一种语言的语法,而是学习创造性地解决问题,从而构建美妙的应用。《像程序员一样思考》分析了程序员解决问题的方法,并且教授你其他图书所忽略的一种能力,即如何像程序员一样思考。全书分为8章。第1章通对几个经典的算法问题切入,概括了问题解决的基本技巧和步骤。第2章通过实际编写C++代码来解决几个简单的问题,从而让读者进一步体会到问题解决的思路和应用。第3到7章是书中的主体部分,分别探......一起来看看 《像程序员一样思考》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

html转js在线工具
html转js在线工具

html转js在线工具