切片

结构体定义

runtime/slice.go文件中

type slice struct {
	array unsafe.Pointer // 数组的指针
	len   int
	cap   int
}

扩容

通过append方法添加数据,返回一个新的slice对象,地址和之前不一样。但是原来元素地址是不变的,直到扩容。

package main

import (
	"fmt"
)

func main() {
	a := make([]int, 1, 2)
	b := append(a, 10)
	fmt.Println(&a == &b) // 变量地址肯定不同,false
	fmt.Println(&a[0] == &b[0]) // true
}

扩容流程

newcap := old.cap
doublecap := newcap + newcap
//这个cap为old.cap+新加元素数量
if cap > doublecap {
	newcap = cap
} else {
	if old.len < 1024 {
		newcap = doublecap
	} else {
		for newcap < cap {
			newcap += newcap / 4
		}
	}
}

cap是老数组的容量+新加元素数量,即扩容的最小值
如果两倍扩容达不到cap,那么新数组的容量就是这个cap
如果两倍扩容达到了cap,那么根据老数组元素数量是否小于1024来决定扩容容量
1. 如果小于1024,那么正常扩容两倍。
2. 如果大于等于1024,那么循环扩容1.25倍,直到达到或者超过cap,最终结果是扩容值。
之后,通过内存对齐得到最终的容量值。

举个例子

package main

import "fmt"

func main() {
	s := []int{1,2}
	s = append(s,4,5,6)
	fmt.Printf("%d %d",len(s),cap(s))
}

结果是5,6

posted on 2023-07-15 10:11  王景迁  阅读(25)  评论(0编辑  收藏  举报

导航