slice是如何扩容的
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容介绍了"slice是如何扩容的"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!问题1,slic
千家信息网最后更新 2026年11月01日slice是如何扩容的问题1,slice的底层数据结构
本篇内容介绍了"slice是如何扩容的"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
问题1,slice的底层数据结构
我擦,这么直接的嘛?
我猜是数组加链表,结果猜错了0分。
翻看源码。
runtime/slice.go
type slice struct { array unsafe.Pointer //数据结构是简单粗暴的数组指针 len int cap int}问题2,slice是如何扩容的
又猜错了~
还是继续看源码吧
从源码找了半天,发现一个这。
growslice handles slice growth during append.
so,就是你了。
func growslice(et *_type, old slice, cap int) slice { // 第三个cap,新的最小容量 //巴拉巴拉巴拉 一堆判断 newcap := old.cap //变量存储空间大小 doublecap := newcap + newcap //双倍空间大小 if cap > doublecap { //如果历史空间大于双倍的容量,新的最小容量 newcap = cap } else { //如果长度小于 1024 新长度就是2倍老容量 if old.len < 1024 { newcap = doublecap } else { //当大于1024 走公式 newcap += newcap / 4,直到newcap大于等于老cap for 0 < newcap && newcap < cap { newcap += newcap / 4 } if newcap <= 0 { newcap = cap } } } var overflow bool var lenmem, newlenmem, capmem uintptr //对et的size做匹配,获取需要申请的空间大小 //1 不处理直接分配 //系统指针大小 进行计算和位运算 //2 唯一运算 //默认 相乘 switch { case et.size == 1: lenmem = uintptr(old.len) newlenmem = uintptr(cap) capmem = roundupsize(uintptr(newcap)) overflow = uintptr(newcap) > maxAlloc newcap = int(capmem) case et.size == sys.PtrSize: lenmem = uintptr(old.len) * sys.PtrSize newlenmem = uintptr(cap) * sys.PtrSize capmem = roundupsize(uintptr(newcap) * sys.PtrSize) overflow = uintptr(newcap) > maxAlloc/sys.PtrSize newcap = int(capmem / sys.PtrSize) case isPowerOfTwo(et.size): var shift uintptr if sys.PtrSize == 8 { // Mask shift for better code generation. shift = uintptr(sys.Ctz64(uint64(et.size))) & 63 } else { shift = uintptr(sys.Ctz32(uint32(et.size))) & 31 } lenmem = uintptr(old.len) << shift newlenmem = uintptr(cap) << shift capmem = roundupsize(uintptr(newcap) << shift) overflow = uintptr(newcap) > (maxAlloc >> shift) newcap = int(capmem >> shift) default: lenmem = uintptr(old.len) * et.size newlenmem = uintptr(cap) * et.size capmem, overflow = math.MulUintptr(et.size, uintptr(newcap)) capmem = roundupsize(capmem) newcap = int(capmem / et.size) } //如果append一次超过过多的元素新增,直接报错,越界,超出容量大小 if overflow || capmem > maxAlloc { panic(errorString("growslice: cap out of range")) } var p unsafe.Pointer //申请新的内存,并把指针指向p if et.ptrdata == 0 { p = mallocgc(capmem, nil, false) memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem) } else { p = mallocgc(capmem, et, true) if lenmem > 0 && writeBarrier.enabled { bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem) } } //将老的数据移动到新的数据 memmove(p, old.array, lenmem) return slice{p, old.len, newcap}}总结
其实可以看出,golang的切片扩容是比较粗暴的,直接赋值拷贝。不过,golang区分的长度和容量两种单位计量,一般会提前分配足够的cap,可以减少maclloc的次数。
"slice是如何扩容的"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
容量
数据
大小
源码
空间
长度
最小
粗暴
内容
双倍
就是
指针
数据结构
数组
更多
知识
结构
问题
巴拉
实用
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网科技公司排名
A股互联网金融科技公司
银优互联网科技有限公司
美国互联网黑科技
易通互联网络科技有限公司
互联网金融 科技创新
银川新华互联网科技学校地址
互联网和高科技公司
云创客互联网科技公司
温州喔噻互联网科技有限公司
银川新华互联网科技职业技术培训学校图片
科技与互联网哪个更好
华服互联网科技官网
互联网软件和科技
爱医互联网络科技
怎样加入科技互联网
互联网相关科技技术
陕西九四连强互联网科技有限公司
华人运通互联网科技公司
黑龙江互联网科技公司
互联网科技工作委员会
北京互联网络科技有限公司
字节跳动和互联网科技
互联网科技有哪些公司
996高科技互联网公司
河南住房之家互联网科技
中国互联网公司排名锤子科技
南博望互联网科技有限公司
伍佰万互联网科技怎么赚钱
深圳无忧互联网科技