golang slice复制范围说明

本文深入探讨了Golang中slice的复制机制,通过具体代码示例解释了slice切片操作的边界条件,包括如何避免越界错误,以及当索引超出slice长度时的行为表现。
golang slice的复制范围说明:

代码简要说明:

func TestSli(t *testing.T) {
	sl := []int{0,1}
	sl2 := make([]int,0)
	for i := range sl{
		fmt.Println("i:",i)
		sl2 = append(sl2,sl[i+1:]...)
	}
	fmt.Println("sl2:",sl2)
}

console output:

i: 0
i: 1
sl2: [1]

下方slice切片从索引1(包含) 到索引4(不包含)
numbers1 = numbers2[1:4]
这里可以看到sl[i+1:]在i=1时候为sl[2:]已经等于了sl的长度2,但是不会报错也不会有值传入。sl[i+1:]中i+1>len(sl)时才会报错。

### 3.1 Go Slice 的底层结构 在 Go 语言中,`slice` 是一种非常重要的基础数据结构,其本质上是对数组的封装和扩展。一个 `slice` 由三个部分组成:指针、长度和容量。具体而言: - **指针(array unsafe.Pointer)**:指向底层数组的起始地址。 - **长度(len int)**:表示当前 `slice` 中元素的数量。 - **容量(cap int)**:表示底层数组的总长度,即 `slice` 可以扩展的最大长度。 这种结构定义如下所示: ```go type slice struct { array unsafe.Pointer // 指向底层数组 len int // 当前长度 cap int // 容量 } ``` 与固定长度的数组不同,`slice` 支持动态扩容,因此可以灵活地进行操作[^4]。 ### 3.2 Slice 的初始化与扩容机制 当使用 `make([]int, 0)` 初始化一个空 `slice` 时,实际上会调用底层函数来创建一个新的 `slice` 实例。此时,该 `slice` 的长度为 0,容量也为 0,且不指向任何有效的底层数组[^1]。 随着元素被不断追加(如 `append(slice, 1)`),如果当前 `slice` 的长度等于其容量,则需要进行扩容操作。扩容过程通常包括以下几个步骤: 1. **计算新容量**:通常情况下,新容量是原容量的两倍,但在某些特殊情况下可能会有所不同(例如当原容量小于一定阈值时)。 2. **分配新内存**:为新的底层数组分配足够的内存空间。 3. **复制数据**:将旧数组中的所有元素复制到新的数组中。 4. **更新指针、长度和容量**:将 `slice` 的指针指向新的数组,并更新长度和容量字段。 通过这种方式,`slice` 能够实现高效的动态增长,同时保持良好的性能表现[^2]。 ### 3.3 Slice 对底层数组的引用与共享 由于 `slice` 仅保存了对底层数组的引用,因此多个 `slice` 可能共享同一个底层数组。这意味着,修改其中一个 `slice` 中的元素可能会影响到其他共享该数组的 `slice`。此外,在进行切片操作(如 `slice[1:3]`)时,生成的新 `slice` 仍然引用原来的底层数组,直到发生扩容或重新赋值为止。 为了防止不必要的内存占用,Go 编译器会在某些情况下强制分离底层数组,例如当某个 `slice` 被修改并且无法再与其他 `slice` 共享同一块内存时。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值