Golang---基本类型(slice)

 


  摘要: 今天我们来学习 Golang 中的一个基本的数据结构 slice, 这个和 C++ 中的 vector 容器思想基本一致,是一个容量可变的数组,那我们就来看下它和 array 的区别和联系,并对其中的典型操作给出分析。

 

回到顶部

数据结构

复制代码
// StringHeader is the runtime representation of a string.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type StringHeader struct {
    Data uintptr
    Len  int
}

// stringHeader is a safe version of StringHeader used within this package.
type stringHeader struct {
    Data unsafe.Pointer
    Len  int
}

// SliceHeader is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

// sliceHeader is a safe version of SliceHeader used within this package.
type sliceHeader struct {
    Data unsafe.Pointer
    Len  int
    Cap  int
}
slice-struct
复制代码

通过上面的结构体,我们可以把 slice 看成一片连续的内存空间加上长度与容量的标识。

 

回到顶部

slice 和 array

  与其它语言一样, slice 是 长度可变的数组,我们其实可以把切片看做是对数组的一层简单封装,因为在每个切片的底层数据结构中,一定会包含一个数组。数组可以被叫做切片的底层数组,而切片也可以被看做是对数组的某个连续片段的引用。

 

回到顶部

slice 的扩容

  这里我们用 append 来向切片追加元素,我们首先会先对切片结构体进行解构获取它的数组指针、大小和容量,如果在追加元素后切片的大小大于容量,那么就会调用 runtime.growslice 对切片进行扩容,扩容就是为切片分配一块新的内存空间并将原切片的元素全部拷贝过去,具体代码如下:

复制代码
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 {
            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            if newcap <= 0 {
                newcap = cap
            }
        }
    }
growslice
复制代码

总结上述代码:1:如果期望容量大于当前容量的两倍就会使用期望容量;

2;如果当前切片的长度小于 1024 就会将容量翻倍;

3:如果当前的切片长度大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量;

 

参考资料:

https://draveness.me/golang/docs/part2-foundation/ch03-datastructure/golang-array-and-slice

https://time.geekbang.org/column/article/14106

 

posted on   爱笑的张飞  阅读(388)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
历史上的今天:
2019-09-03 one_day_one_linuxCmd---netstat命令
2019-09-03 docker---Dockerfile编写
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示