slice

在切片的 index 位置插入元素

copy(res[index+1:],res[index:])	// 将 slice 从 index 位置后移,空出 index 位置
res[index]=value

底层

type slice struct {
// 指针指向底层的数组
    array unsafe.Pointer
	// 当前切片所使用的长度
    len   int
    // 底层数组的长度
	cap   int
}
qv8Q5C

在复制切片时,底层的数组也被复制,导致在新的复制生成的切片发生扩容前,其内部的 array unsafe.Pointer 与原切片的 array 指针指向的是同一底层数组,此时对newSlice 的修改会影响oldSlice——>发生扩容后则不会

扩容算法:

  • 所需最小 MinCap>2*oldCap newCap=Mincap

  • 原 slice 长度 len<1024则两倍扩容

  • 原 slice 长度len>1024 则 1.25 倍扩容

  • 最后进行内存对齐

    // 扩容算法
	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

Tips:

  • 打印%p可以输出 slice 指向的底层数组的地址
  • 创建 slice 时候使用mallocgc函数分配内存,如果创建的 size==0则返回固定的 slice 的底层数组地址
    • 使用 s:=make([]int,0)s:=[]int{} 创建则 len==0 默认地址
    • 使用var s []int 则底层数组指针为 nil

逆序slice

// 辅助空间
resTrue:=make([] int,len(res))
for index:=range res {
    resTrue[index]=res[len(res) - 1-index]
}

// 原地逆序

for i:=0;i<len(res)>>1; i++{
    res[i],res[len(res) - 1-i]=res[len(res) - 1-i],res[i]
}