当前位置:网站首页>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其实还是一次调用函数的操作)
边栏推荐
猜你喜欢
随机推荐
Three handshakes, four waves
App testing
VMware virtual machine cannot be connected to the Internet after forced shutdown
OpenHarmony轻智能产品开发直播笔记
Shell编程之正则表达式
账号和权限管理
Win10电脑的WLAN消失的故事
Process synchronization and mutual exclusion problem
浅谈Flask_script
监视文本框的输入
Euclid and the game
The principle and configuration of VLAN
正则表达式基础介绍
网络布线及数制转换
系统安全及应用
web basic concepts
VRRP原理及配置
jdbctemplate connects to sql server, the data found in the code is inconsistent with the database, how to solve it?
.net(五) 业务层实现
实现弹簧柔性状态的2种方式 | Solidworks教程









