Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)
Posted 寂静花开
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)相关的知识,希望对你有一定的参考价值。
目 录
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其实还是一次调用函数的操作)
以上是关于Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)的主要内容,如果未能解决你的问题,请参考以下文章
Go语言技巧之正确高效使用slice(听课笔记总结--简单易懂)
《Go语言精进之路》读书笔记 | 了解切片实现原理并高效使用
Go语言:SliceHeader,slice 如何高效处理数据?