go slice切片

go slice 切片

https://juejin.cn/post/6979108608122290212

结构体

type slice struct {
array unsafe.Pointer//指针
len int // 长度
cap int // 容量
}

定义的三种方式

1、var 切片名 []type

var s []int

2、使用make()函数定义,make([]type,len)

var s []int = make([]int,1) //len=1 cap=1

3、指定容量make([]type, len, cap),len初始化长度,cap为可变参数

var s []int = make([]int,3,4) //s [0 0 0]

容量

容量的用途是append扩容时,如果新的长度小于容量,不会更换底层数组,内存地址不变;否则,go会重新申请一个底层数组,拷贝这边的值过去,把原来的数组丢掉,内存地址改变(已经是一个新的数组)。

扩容

func growslice(et *_type, old slice, cap int) slice {
...........
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
}
}
}
...........
}
  1. 如果预估新的容量大于容量的2倍,直接使用新容量;
  2. 不满足情况1,老的容量小于1024,则新的容量直接等于就容量的2倍;
  3. 不满足情况2,就容量大于等于1024,则旧容量小于需要的容量,则就容量不停的*1.25,直到大于新容量。
func TestSlice(t *testing.T) {
s := make([]int,1024,1024)
// 旧容量1024
fmt.Println(cap(s)) // 1024
s = append(s,1)
// 扩容完 1024 * 1.25 = 1280
fmt.Println(cap(s)) // 1280
add := make([]int,255)
s = append(s,add...)
// 再添加255个元素正好达到1280,容量不变
fmt.Println(cap(s)) // 1280
// 神奇的事情发生了,再次扩容应该为1280 * 1.25 = 1600,但实际为1696
s = append(s,1)
fmt.Println(cap(s)) // 1696
}
posted @   凌易说-lingyisay  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示