一个go切片的问题
var i = 3
nums := []int{1, 2, 3, 4, 5, 6}
nums6 := append(nums[:i], nums[i+2:]...)
fmt.Println(nums, nums6)
这段代码nums 最终输出为什么变成了[1,2,3,6,5,6]
输出内容为:// [1 2 3 6 5 6] [1 2 3 6]
看这个输入nums应该是改动了,但是为什么5,6又还在呢
一个go切片的问题
var i = 3
nums := []int{1, 2, 3, 4, 5, 6}
nums6 := append(nums[:i], nums[i+2:]...)
fmt.Println(nums, nums6)
这段代码nums 最终输出为什么变成了[1,2,3,6,5,6]
输出内容为:// [1 2 3 6 5 6] [1 2 3 6]
看这个输入nums应该是改动了,但是为什么5,6又还在呢
在 Go 语言中,切片是对底层数组的引用,而不是对底层数组的一个副本。这意味着当你创建一个新的切片时,如果你没有创建新的底层数组,那么新的切片和原来的切片会共享同一个底层数组。
现在,让我们分析你提供的代码:
var i = 3
nums := []int{1, 2, 3, 4, 5, 6}
nums6 := append(nums[:i], nums[i+2:]...)
fmt.Println(nums, nums6)
nums
是一个包含 6 个整数的切片。i
被设置为 3。nums6
是通过 append
函数创建的,该函数将 nums
切片的前 i
个元素(即 nums[:i]
)和从 i+2
开始到 nums
结尾的所有元素(即 nums[i+2:]
)合并到一个新的切片中。这里的关键是 append
函数如何工作。在 Go 中,append
函数可能会重新分配底层数组,特别是当切片没有足够的容量来容纳额外的元素时。但是,在你的例子中,nums[:i]
和 nums[i+2:]
都没有超出 nums
的容量,所以 append
函数不需要重新分配底层数组。
因此,nums6
切片和 nums
切片共享同一个底层数组。当你修改 nums
切片时(在这个例子中是 nums[i] = 6
),你实际上是在修改两个切片共享的底层数组。
最终,当你打印 nums
和 nums6
时,你会看到 nums
的值已经被改变,因为它和 nums6
共享同一个底层数组。
为了避免这种情况,你可以在创建 nums6
时创建一个新的底层数组,如下所示:
nums6 := append([]int{}, nums[:i]...)
nums6 = append(nums6, nums[i+2:]...)
这样,nums6
会有一个独立的底层数组,对 nums6
的修改不会影响 nums
。
slice 里只记录了 underlying array 跟 length 一类的 meta data。
append 不会直接改变 nums ,而是修改了 underlying array 的内容,并且重新生成了一个新的 slice (nums6) 。
所以 nums 的 length 是没有变化。
另外 array 的长度是不能修改的。所以对 nums 来说,它的 underlying array 被修改了一个元素,长度没有变化,最后的 5,6 就都还在
15 回答8.4k 阅读
7 回答5.3k 阅读
6 回答6.8k 阅读✓ 已解决
4 回答4.4k 阅读✓ 已解决
4 回答4k 阅读
1 回答3.1k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
看官方对
append
描述,Appending_and_copying_slices首先
append
用法:里面这么说的:
如果
append
之后的数据并没有超过s
原本的容量,那么就会利用原本的底层数组
,也就是你等于是在原切片的底层数据上对应位置进行了改动。然后对于切片的解释: slices-intro

golang中切片由三部分组成:
所以结合
append
不超过原本切片对象的容量时候,在原本指针所指向的underlying array
做了修改,并返回;如果超过原本切片的容量,那就会重新reallocate
一个新的underlying array
予以返回。将你的例子进行扩展,不改变容量的时候:
就是这个道理。。。