当前位置:网站首页>Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)
Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)
2022-08-09 08:16:00 【寂静花开】
slice基本
切片slice 相当于“动态数组”,但他并不是数组或数组指针,它通过内部指针和相关属性来引用数组片段,以实现变长的功能。
Slice源码中的数据结构:
type slice struct {
array unsafe.Pointer // 指向底层数组
len int // 长度
cap int // 容量
}
所以,slice代表变长的序列,它的底层是数组。
一个切片由3部分组成:指针、长度和容量。
指针指向底层数组,长度代表slice当前的长度,容量代表底层数组的长度。
换句话说,slice自身维护了一个指针属性,指向它底层数组的某些元素的集合
正确使用slice
这部分内容通过case来讲解,觉着简单的case可跳过。
case1
下面这段代码输出什么?
func main() {
var s []int
for i := 0; i < 3; i++ {
s = append(s,i)
}
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s[0] = 1024
}
正确输出:[1024 1 2]
其中,
append函数:在切片s末尾添加元素i
fmt:是go的一个标准库,fmt包实现了类似C语言printf和scanf的格式化I/O
case2
下面这段代码输出什么?
func main() {
var s []int
for i := 0; i < 3; i++ {
s = append(s,i)
}
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s = append(s, 2048)
s[0] = 1024
}
正确输出:[1024 1 2]
如图所示,两个S不同,但指向同一个array地址,最后按main中S的长度输出,所以是[1024 1 2]
case3
下面这段代码输出的是什么?
func main() {
var s []int
for i := 0; i < 3; i++ {
s = append(s, i)
}
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s = append(s, 2048)
s = append(s, 4096)
s[0] = 1024
}
正确输出:[0 1 2]
切片通过 append扩容时,如果切片长度小于当前的容量,那么切片不会扩容,如果追加元素后切片长度大于当前的容量时,切片就会扩容,扩容机制如下:
- 当扩容之后的元素长度小于 1024 时会以原切片容量的 2 倍的进行扩容;
- 当扩容之后的元素长度大于 1024 时会以原切片容量的 1.25倍的进行扩容;
- 当不需要扩容时,append 函数返回的是原底层数组的原切片(内存地址不变);
- 当切片需要扩容时,append 函数返回的是新底层数组的新切片(切片内存地址发生了改变);
我们设main中s为S1,modifySlice中的s为S2
所以,Append 4096 后 容量由原来的4扩容成8,开辟了新地址,S2与S1不再指向同一地址。
而更改成1024的,是新地址切片。而输出是main中指向老地址的S1.
2048实际也被写入了原始切片S1,但是println函数是根据len来打印的,所以没有打印出来。
case4
func main() {
var s []int
for i := 0; i < 3; i++ {
s = append(s, i)
}
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s[0] = 1024
s = append(s, 2048)
s = append(s, 4096)
}
正确输出:[1024 1 2]
case4中,1024是更改到还未扩容到老地址上的切片S1中,所以输出的时候有1024.
高效使用slice
1、简单粗暴:直接定义slice,然后进行append操作(性能比较差)
2、预分配容量然后进行append操作(比第一种好)
3、容量和长度都分配完再进行append操作(最快的)
- 预先分配内存可以提升性能(CPU是比内存更加珍贵的资源)
- 直接使用index赋值而非append可以提升性能(append其实还是一次调用函数的操作)
边栏推荐
猜你喜欢
OpenHarmony Light Smart Product Development Live Notes
磁盘管理与挂载
VLAN的原理及配置
P1064 Jin Ming's Budget Plan
Notes on OpenHarmony Open Source Meeting (Nanjing Station)
HOOPS是什么?这4款3D软件开发工具包你还不知道?
Shell编程之正则表达式
scp upload file to remote server
[MySQL]mysql: Solve the problem of [Err] 1093 - You can't specify target table 'table name' for update in FROM clause
LAN Technology - 6MSTP
随机推荐
数据库中的操作(语法)
3D软件开发工具HOOPS全套产品开发介绍 | HOOPS Visualize、HOOPS Publish
OpenHarmony Light Smart Product Development Live Notes
bs4的使用基础学习
Conversion between number systems
The Martian - Simple Math Problems
MySql homework practice questions
eTS UI development learning
可能导致Loadrunner检查点中savecount为0的分析
正则表达式基础介绍
【redis】redis之过期监听
三次握手,四次挥手
欧几里和游戏
Non-decreasing Array
Euclid and the game
账号和权限管理
Buns make up the number----Euclide+dp
eTS UI开发学习
matlab——解线性方程组 与 非线性方程组
I'm here to advertise