golang切片使用append追加内容导致切片值异常问题

在一次对切片合并处理后,原本是希望在得到一个新的切片同时不改变原切片,以前做过类似的处理,是没有问题的,但是这次发现原切片的值也被改变了,

示例代码:

s1 := []int{1, 2, 3, 4}
s2 := []int{-1, -2, -3}

s3 := append(s1[:1], s2...)

fmt.Println(s3)
fmt.Println(s1)

  

 

打印结果:

[1 -1 -2 -3]
[1 -1 -2 -3]

 

之前处理过类似情况,s1的值并没有被改变,但是这次却改变了。

 

原因分析


根据上面描述,基本可以判断出是append的错误应用造成的,因此重新对对append的用法进行学习,经过查阅相关资料,确定了append有以下两个原则:

(1)append函数调用后,应该使用返回值作为结果。

(2)append函数调用后,不应该再使用实参传入的slice。
所以使用append函数一般都是s = append(s,elem1)这种用法,也就是把结果重新赋值给原来的slice。

 

官方解释:

slice的底层存储依赖于底层数组(underlying array)。

 

例子中,s1初始化的值是[]int{1, 2, 3, 4},它的len和cap都是4,所以它的底层数组是一个长度为4的数组[4]int{1,2,3,4}
基于slice的特点,s1[:1]和s1是共享底层数组的,所以s1[:1]这个slice的改变是会影响到underlying array的。

 

而之所以以前可以得到一个新的切片s3且不改变s1,是因为:

新切片的容量不能容纳所有追加元素,append会申请一个新的底层数组用来存储,也会返回一个新的slice,这不会影响到原本的底层数组,也就不会影响到原本的slice。

 

解决方案


不应该将append的返回值赋给新变量,而应该重新赋值给要追加元素的切片

上面示例修改为:

s1 := []int{1, 2, 3, 4}
s2 := []int{-1, -2, -3}

s1 := append(s1[:1], s2...)

  

 

 

原文地址:https://www.cnblogs.com/yourstars/p/15186597.html