【Go实战基础】slice 切片为什么更常用
数组元素固定,在 Go 语言中没有那么常用,更常用的数据结构是切片。
什么是切片呢? 切片就是动态的数组,它的长度不固定,可以随意向切片中追加元素,而且切片会在容量不足的时候自动扩容。
切片(slice)是对数组一个连续片段的引用,这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内,切片提供了一个与指向数组的动态窗口。
切片的数据结构如下:
1 2 3 4 5 6 7 8 9 10 | type slice struct { // Pointer 是指向一个数组的指针 array unsafe.Pointer // 当前切片的长度 len int // cap 是当前切片的容量。cap 总是大于等于 len 的。 cap int } |
Pointer 作为一个指针指向的数组是一片连续的内存空间,这片内存空间可以用于存储切片中保存的全部元素,底层存储都是连续的,所以可以将切片理解为一片连续的内存空间加上长度与容量的标识。
1 | 实战需求: slice 切片的实现原理 |
马上安排!
一、工程目录
1 | cd go -003/ |
二、创建 g003.go
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 32 33 | /* * @Author: 菜鸟实战 * @FilePath: /go110/go-003/g003.go * @Description: slice 切片 */ package main import ( "fmt" "runtime" ) // 主函数 func main() { // 使用内置函数打印 println( "Hello" , "菜鸟实战" ) //定义一个无初始长度的切片 s := []string{} for i := 0; i < 6; i++ { // 拼接元素 s = append(s, "eeeee" ) // 拼接后会动态扩容 fmt.Printf( "容量: %v, 长度 : %v \n" , cap(s), len(s)) } // 使用包函数打印 fmt.Printf( "版本: %s \n" , runtime.Version()) } |
三、编译和运行
# 1、生成模块依赖
1 | go mod init g003 |
1 2 | go build g003. go |
└── go-003 ├── g003 ├── g003.go └── go.mod
go run g003
四、运行结果
Hello 菜鸟实战
容量: 1, 长度 : 1
容量: 2, 长度 : 2
容量: 4, 长度 : 3
容量: 4, 长度 : 4
容量: 8, 长度 : 5
容量: 8, 长度 : 6
版本: go1.17.10
由输出结果可以看到,Slice 的容量会自动扩容的起点是 2,当长度大于 2 时,slice 的容量会自动扩容为原来的 2 倍,每一次扩容都会重新开辟一块内存空间,将旧的数据复制到新开辟的内存空间中,然后释放旧的内存空间。
数组长度是固定的,而 Go 中使用的切片设计想法是由动态数组概念而来,可以用来管理数据集合,并可以自动增加和减少,但是切片本身并不是动态数据或者数组指针,与此同时,切片还具有可索引,可迭代的优秀特性,因此使用也更为广范。
菜鸟实战,持续学习!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下