当前位置: 首页 > news >正文

go的基础数据结构 slice源码阅读

1.slice(runtime/slice)

1.1slice结构体

type slice struct {array unsafe.Pointer  // 指向底层数组的指针len   int            // 切片长度cap   int            // 切片容量
}type notInHeapSlice struct {array *notInHeap     // 非堆内存切片len   intcap   int
}

notInHeapSlice 的作用

notInHeapSlice 是一个特殊的切片结构体,它的主要作用是:

1. 非堆内存切片

        这是一个由 internal/runtime/sys.NotInHeap 内存支持的切片,与普通的 slice 结构体不同,notInHeapSlice 的底层数组指向的是非堆内存区域

2.用途

        从代码中的使用情况可以看出,notInHeapSlice 主要用于:

        内存管理器的内部数据结构:如 mbitmap.go、mpagealloc_*.go、mheap.go 等;

        运行时系统的底层组件:如内存分配器、垃圾收集器等;避免垃圾收集器的干扰:这些内存区域不需要被 GC 管理
3.性能优势
避免写屏障:指向非堆内存的指针可以省略写屏障,提高性能
内存管理控制:运行时可以完全控制这些内存的分配和释放
避免 GC 扫描:这些内存不会被垃圾收集器扫描,减少 GC 开销

1.2 makeslice函数

func makeslice(et *_type, len, cap int) unsafe.Pointer {mem, overflow := math.MulUintptr(et.Size_, uintptr(cap))if overflow || mem > maxAlloc || len < 0 || len > cap {// 错误处理逻辑panicmakeslicelen()  // 长度超出范围panicmakeslicecap()  // 容量超出范围}return mallocgc(mem, et, true)  // 分配内存
}

计算所需内存:元素大小 × 容量
检查溢出、内存限制和参数有效性
使用mallocgc进行垃圾回收友好的内存分配

1.3 makeslicecopy函数

将切片进行复制转移

// makeslicecopy 分配一个类型为 "et"、长度为 "tolen" 的切片,
// 然后从 "from" 中复制 "fromlen" 个类型为 "et" 的元素到新分配的内存中。
func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer {var tomem, copymem uintptrif uintptr(tolen) > uintptr(fromlen) {var overflow booltomem, overflow = math.MulUintptr(et.Size_, uintptr(tolen))if overflow || tomem > maxAlloc || tolen < 0 {panicmakeslicelen()}copymem = et.Size_ * uintptr(fromlen)} else {// fromlen 是已知有效的长度,并且大于等于 tolen,// 因此 tolen 作为目标切片长度也有效(因为元素宽度相同)。tomem = et.Size_ * uintptr(tolen)copymem = tomem}var to unsafe.Pointerif !et.Pointers() {to = mallocgc(tomem, nil, false)if copymem < tomem {// 清除未初始化的内存区域(无指针类型无需GC扫描)memclrNoHeapPointers(add(to, copymem), tomem-copymem)}} else {// 不能使用 rawmem(跳过内存清零),因为GC可能会扫描未初始化的内存to = mallocgc(tomem, et, true)if copymem > 0 && writeBarrier.enabled {// 仅标记源指针(目标切片已通过分配清零)// 传入类型是优化操作,因为源和目标都只包含完整et类型值// 详见 bulkBarrierPreWrite 注释bulkBarrierPreWriteSrcOnly(uintptr(to), uintptr(from), copymem, et)}}if raceenabled {callerpc := sys.GetCallerPC()pc := abi.FuncPCABIInternal(makeslicecopy)// 竞态检测:记录内存读取范围racereadrangepc(from, copymem, callerpc, pc)}if msanenabled {// 内存安全检测:标记读取区域msanread(from, copymem)}if asanenabled {// 地址消毒检测:标记读取区域asanread(from, copymem)}// 内存复制操作memmove(to, from, copymem)return to
}

1.4核心扩容策略

newLen = oldLen+num

即 sli = append(sli, make([]int, 1000)) 那么num即是1000 oldLen即是cap(sli)

func nextslicecap(newLen, oldCap int) int {newcap := oldCapdoublecap := newcap + newcapif newLen > doublecap {return newLen  // 如果新长度超过2倍容量,直接使用新长度}const threshold = 256if oldCap < threshold {return doublecap  // 小切片:容量翻倍}// 大切片:平滑过渡到1.25倍增长for {newcap += (newcap + 3*threshold) >> 2  // 约1.25倍增长if uint(newcap) >= uint(newLen) {break}}return newcap
}
http://www.dtcms.com/a/406317.html

相关文章:

  • 百度网盟推广 网站四川建设网有限责任公司官网
  • 破局渠道垄断:青蓝的流量入口变现路径
  • 【C++STL :string类 (二) 】从接口应用到内存模型的全面探索
  • 学做面包到什么网站网站点击按钮回到页面顶部怎么做
  • 领航 网站设计主机屋怎么做网站
  • 在VTK中实现相机自动绕轴旋转
  • 关于解决switch开关属性中active-value=“1“为数值形失败的问题
  • Seata 深度解析:微服务分布式事务管理的实践指南
  • LeetCode:53.课程表
  • 中国县域经济韧性(2006-2021)
  • MySQL零基础学习Day3——函数和约束
  • Bililive-go+cpolar:跨平台直播录制的远程管理方案
  • 飞马无人机正射/倾斜影像数据预处理
  • 2025 AI 技术跃迁与产业融合:从实验室到价值场
  • 济源网站建设价格蓝色系网站
  • MySQL InnoDB缓冲池优化全指南
  • Redis 内存淘汰策略 LRU 和传统 LRU 差异
  • 焞煌网站怎么做产品营销型网站建设
  • 【C++】:stack、queue和deque全面讲解
  • 【MySQL学习笔记】数据库的CURD(一)
  • 使用Excel在标签打印软件快速新建标签,表格导入并实现批量打印
  • WEB日常刷题练习(1)
  • 信阳网站建设的费用潍坊网站建设维护
  • Kafka-消息不丢失
  • 如何查看一个网站用什么程序做的wordpress文章发布保存都不行
  • ReactFlow:构建交互式节点流程图的完全指南
  • 实战:基于 BRPC+Etcd 打造轻量级 RPC 服务——从注册到调用的核心架构与基础实现
  • 多语言网站建设幻境网站开发人员的岗位有
  • 19.9咖啡项目:工程项目级别的IIC主从机模块
  • 【遥感技术】​从CNN到Transformer:基于PyTorch的遥感影像、无人机影像的地物分类、目标检测、语义分割和点云分类