Go 切片的内部操作是否影响原始切片的外部?
例如:Go 切片的内部操作是否影响原始切片的外部?,go,slice,Go,Slice,例如: func test(requiredIp []int, i int) []int { requiredIp = append(requiredIp[0:i], requiredIp[i+1:]...) return requiredIp } func main(){ requiredIp := []int{1,2,4,5,6} fmt.Println(test(requiredIp,0)) // output:[2 4 5 6] fmt.Prin
func test(requiredIp []int, i int) []int {
requiredIp = append(requiredIp[0:i], requiredIp[i+1:]...)
return requiredIp
}
func main(){
requiredIp := []int{1,2,4,5,6}
fmt.Println(test(requiredIp,0)) // output:[2 4 5 6]
fmt.Println("original", requiredIp) // output:[2 4 5 6,6]
}
为什么原始切片有两个6?切片是一种结构类型,有三个字段:
- 指向包含数据的底层数组(的地址)的指针
- 长度-切片中有多少个元素
- 容量—在不重新分配基础阵列的情况下,可以将多少元素存储到基础阵列中
由值(即复制)表示的是包含三个字段的结构。
复制的指针显然指向与原始切片中相同的数据块 代码中发生的情况如下所示:
[]int{1,2,4,5,6}
。
它的长度和容量等于5
test
通过函数的参数
requiredIp
获得的切片最初与调用中传递的切片相同
requiredIp[0:i]
重新切片,因为在调用i
时等于0,所以计算requiredIp[0:0]
该表达式使用支持数组和原始切片的容量以及长度0创建一个切片
requiredIp[i+1://code>,在您的调用中是requiredIp[1://code>
结果与原始结果共享备份数组,容量为4,内容为[]int{2,4,5,6}
也就是说,切片的支持数组仍然保持
[1,2,4,5,6]
被追加的切片与被追加的切片共享相同的支持数组,只是它指向第1个元素,而不是第0个元素
append
的代码看到它被告知要追加4个元素,并检查目标片是否有足够的容量容纳它们,并且它有。因此,
append
仅将[2,4,5,6]
从同一个备份数组复制到同一个备份数组,覆盖其中从索引0开始的4个元素。实际上,它的元素[2,4,5,6]
向左移动了一个元素
生成的备份数组现在包含[2,4,5,6,6]
:前4个元素是最后4个元素,向左移动一个元素,覆盖索引0到3处的内容
append
将4个元素追加到长度为0的切片
长度的差异解释了为什么“原始”切片中似乎有“额外的”
6
。事实上,在调用test
之前,它的位置正好被省略了
test
生成的切片与原始切片“分离”,则有几种可能性:
- 仅将附加到未分配的片上-例如,
将分配一个新的后备数组 在您的特定情况下,这并不像append([]int(nil),1,2,3,4)
那样是一个真正的解决方案,i>0
必须在一个非空片上操作。对于exmaple,这可以通过两个附录来解决:append
…或通过分配新切片和s:=append([]int(nil),输入[0:i]…) s=追加(s,输入[i+1:]…)
ing:copy
s:=make([]int,len(输入)-1) 复制,输入[0:i]) 复制(s[i:],输入[i+1:])
- 重新选择原始切片时,请确保还人为地重置其容量:
在这里,第一个片的容量与它的长度相同,returnappend(输入[0:i:i],输入[i+1:]…)
,即使向它追加一个元素,也会迫使i
分配一个新的后备数组,将这些append
元素复制到它上面,然后复制所追加的内容i
……实际上考虑开始。
切片由数组支持,并且尽可能地将原始数组的副本共享,使数组首先被分配。我们可以使用z:=test(requiredIp,0)显示test函数返回的切片包含所有值;fmt.Println(z[:5])
对于切片,索引上限是切片容量上限(a),而不是长度