博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang中切片slice的使用须知
阅读量:3986 次
发布时间:2019-05-24

本文共 3559 字,大约阅读时间需要 11 分钟。

这篇文章主要理解一个事情:切片是对数组的引用。

go version

1.14.7

乍一看,这个很好理解,但是却很容易出错。

切片的主要操作:

1、make			创建一个切片。2、len			切片的长度。3、cap			切片的容量。4、append		向切片中填加数据到尾部,实际上是修改底层数组对应位置上的值。5、a = a[:0]	清空一个切片。6、a[0]			访问值。7、copy			复制一个切片。

切片的三要素:

pointer - 底层数组的某一个元素的地址,不一定是第一个,数组的各个元素的地址是连续的。len(a)	- 切片的长度。 cap(a)	- 底层数组的长度。
创建一个切片的步骤为:m := make([]int,  n)1、创建一个数组 [n]int 2、m的pointer为数组的地址,len为n,cap为n。
case1

如果 n 为 0 呢?

m := make([]int, 0)n := make([]int, 0)t := make([]int, 0)fmt.Printf("%p\n", m) // 0x5ae008fmt.Printf("%p\n", n) // 0x5ae008fmt.Printf("%p\n", t) // 0x5ae008

golang在底层为长度等于0的数组指向了同一个地址。

cc := [0]int{
}fmt.Printf("%p\n", &cc) // 0x5ae008
case2

append一定会导致切片扩容吗?

关于扩容,当底层数组长度不够了,会创建一个新的数组,将原数据拷贝过来,同时切片的pointer为新数组的首地址,每次会扩容多少呢,按照既定的策略来,每个版本可能不一样。

既然有策略存在,那肯定不是每次添加数据都会取扩容的。

那么,以下程序会触发扩容吗?

s1 := make([]int, 0)fmt.Printf("%p\n", s1) // 0x5ae008s1 = append(s1, 1)fmt.Println(len(s1)) // 1fmt.Println(cap(s1)) // 1fmt.Printf("%p\n", s1) // 0xc00000a0f8s1 = append(s1, 10, 11)fmt.Println(len(s1)) // 3fmt.Println(cap(s1)) // 4fmt.Printf("%p\n", s1) // 0xc000014440s1 = append(s1, 6)fmt.Println(len(s1)) // 4fmt.Println(cap(s1)) // 4fmt.Printf("%p\n", s1) // 0xc000014440 没有发生扩容
case3

如何理解切片的容量cap?

切片是构建在数组之上的,切片的pointer指向数组中的某一个元素的地址,直到数组的尾部,这个区间就是切片的容量,也是切片的作用区间

切片的长度,表示切片已经存储了几个元素,可以通过下标来访问。

切片的容量的意义就在于,执行append操作时如果超出了容量,系统需要对数组进行扩容,此时就会将切片的内容复制到新的数组上。

a := make([]int, 0)a = append(a, 1,2,3,4,5,6)fmt.Printf("%p\n", a) // 0xc000012330fmt.Println(len(a)) // 6fmt.Println(cap(a)) // 6b := a[:0]fmt.Printf("%p\n", b) // 0xc000012330fmt.Println(len(b)) // 0fmt.Println(cap(b)) // 6c := a[2:4]fmt.Printf("%p\n", c) // 0xc000012340 地址在a的后面fmt.Println(len(c)) // 2fmt.Println(cap(c)) // 4

在这里插入图片描述

case4

切片为引用传递。

指向同一个底层数组的多个切片会相互影响的,具体影响的范围取决于各个切片的作用区间

a := []int{
1,2,3,4,5,6,7,8}fmt.Printf("%p\n", a) // 0xc00000c540fmt.Println("------------------------------------")a1 := a[:3] // [1 2 3]fmt.Printf("%p\n", a1) // 0xc00000c540fmt.Println(len(a1)) // 3fmt.Println(cap(a1)) // 8fmt.Println("------------------------------------")a2 := a[:5] // [1 2 3 4 5]fmt.Printf("%p\n", a2) // 0xc00000c540fmt.Println(len(a2)) // 5fmt.Println(cap(a2)) // 8fmt.Println("------------------------------------")a3 := a[4:] // [5 6 7 8]fmt.Printf("%p\n", a3) // 0xc00000c560fmt.Println(len(a3)) // 4fmt.Println(cap(a3)) // 4fmt.Println("------------------------------------")a1[0] = 10fmt.Println(a) // [10 2 3 4 5 6 7 8]fmt.Println(a1) // [10 2 3]fmt.Println(a2) // [10 2 3 4 5]fmt.Println(a3) // [5 6 7 8]fmt.Println("------------------------------------")a1 = append(a1, 11)fmt.Println(a) // [10 2 3 11 5 6 7 8]fmt.Println(a1) // [10 2 3 11]fmt.Println(a2) // [10 2 3 11 5]fmt.Println(a3) // [5 6 7 8]fmt.Println("------------------------------------")a3 = append(a3, 12) // 已经扩容到新的数组fmt.Println(a) // [10 2 3 11 5 6 7 8]fmt.Println(a1) // [10 2 3 11]fmt.Println(a2) // [10 2 3 11 5]fmt.Println(a3) // [5 6 7 8 12]
case5

如何做到复制切片,但不需要引用。

func copy(dst, src []Type) int

dst 必须是一个初始化了的,且长度大于0的切片,dst和src的类型要一致, copy并不会自动扩容

a := []int{
1,2,3,4,5,6,7,8}fmt.Printf("%p\n", a) // 0xc00000c4c0var b []intcopy(b, a)fmt.Printf("%p\n", b) // 0x0fmt.Println(b) // []c := make([]int, 0)copy(c, a)fmt.Printf("%p\n", c) // 0x5ac008fmt.Println(c) // []d := make([]int, len(a))copy(d, a)fmt.Printf("%p\n", d) // 0xc00000c500fmt.Println(d) // [1 2 3 4 5 6 7 8]e := make([]int, 4)copy(e, a)fmt.Printf("%p\n", e) // 0xc000014480fmt.Println(e) // [1 2 3 4]

copy的使用场景:

有时候一个小的切片来自于一个大的切片的一部分(b := a[m:n]),因此它们指向同一个大的底层数组,虽然在此之后大的切片已不再使用,但是底层数组依然不会被释放,因为小的切片还在指向它,所以此时应该使用copy来产生小的切片(copy(b, a)),这样可以减少内存占用。

转载地址:http://ijaui.baihongyu.com/

你可能感兴趣的文章
微服务架构的设计模式
查看>>
技术领导力:作为技术团队领导经常为人所忽略的技能和职责
查看>>
持续可用与CAP理论 – 一个系统开发者的观点
查看>>
nginx+tomcat+memcached (msm)实现 session同步复制
查看>>
c++数组指针和指针数组详解
查看>>
c++指针常量与常量指针详解
查看>>
c++字符数组和字符指针区别以及str***函数
查看>>
c++的string类初始化及其常用函数
查看>>
c++类的操作符重载注意事项
查看>>
c++模板与泛型编程
查看>>
STL分配器allocator
查看>>
STL::deque以及由其实现的queue和stack
查看>>
WPF与MVVM的实现(四)命令绑定
查看>>
WPF与MVVM的实现(三)List的数据绑定
查看>>
CS4344驱动
查看>>
WAV文件解析
查看>>
DAC输出音乐2-解决pu pu 声
查看>>
WPF中PATH使用AI导出SVG的方法
查看>>
WPF UI&控件免费开源库
查看>>
QT打开项目提示no valid settings file could be found
查看>>