golang中slice底层实现

化蝶飞618 · · 764 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

什么是切片

切片就是我们经常所说的动态数组,可以灵活的增加和减少切片内的元素。
常见的切片操作有:reslice、append、copy

切片和数组该如何选择呢?

区别

切片是引用类型,数组是值类型。那么数组在复制和函数传参时候都是值复制。

优缺点

数组作为函数传参,当数组比较大时候往往会造成资源浪费。
切片是引用传递,所以它们不需要使用额外的内存并且比使用数组更有效率。

底层的数据结构

首先切片本身并不是动态数组或者数组指针,它是通过指针引用底层数组,本身是一个只读对象,其工作机制类似数组指针的一种封装。
切片数据结构定义:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

切片的结构体由3部分构成,Pointer 是指向一个数组的指针,len 代表当前切片的长度,cap 是当前切片的容量。cap 总是大于等于 len 的。

创建切片

两种形式:make 创建切片,空切片。

  • make
slice := make([]int,4,6)

创建了一个len是4,容量是6的切片。、
字面量也可以创建切片

slice := []int{1,2,3,4,5}

需要注意的是 [ ] 里面不要写数组的容量,因为如果写了个数以后就是数组了,而不是切片了。

  • 空切片
var slice []int

切片扩容

一个是扩容时候的策略,还有一个就是扩容是生成全新的内存地址还是在原来的地址后追加。
扩容不像java那样通过负载因子触发,具体策略如下:

  • 首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)
  • 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap)
  • 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的 1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
  • 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)

切片拷贝

完整复制一个切片,

array := []int{1, 2, 3, 4}
slice := make([]int, len(array))
n := copy(slice, array)
fmt.Println(n,slice)

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:化蝶飞618

查看原文:golang中slice底层实现

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

764 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传