Go之Slice(切片)

作者: Jabir_Zhang | 来源:发表于2019-07-12 01:08 被阅读10次

内部结构

切片表面上用起来像是一个可变数组,但它其实是一个结构体,内部结构如下:


切⽚内部结构

切片分为三个参数

  1. 指针,指向一片连续的存储空间,也就是数组
  2. len(长度),我们可以访问的数组元素个数
  3. cap(容量),指针指向的数组的储存空间的长度

len和cap到底具体是什么意思,有什么区别?
我们可以通过代码来打印下长度和容量来观察

var s0 []int
t.Log(len(s0), cap(s0)) //打印结果0 0
s0 = append(s0, 1)
t.Log(len(s0), cap(s0)) //打印结果1 1

一开始初始化,没有元素,所以len和cap都是0。append一个元素1后,len和cap都增长成了1。

s1 := []int{1, 2, 3, 4}
t.Log(len(s1), cap(s1)) //打印结果4 4

len和cap都是4。

s2 := make([]int, 3, 5)
t.Log(len(s2), cap(s2))  //打印结果3 5
t.Log(s2[0], s2[1], s2[2]) 
t.Log(s2[0], s2[1], s2[2], s2[3]) //报错,len仅为3,因此访问第4个元素报错
s2 = append(s2, 1)
t.Log(s2[0], s2[1], s2[2], s2[3])
t.Log(len(s2), cap(s2)) //打印结果4 5

在申明切片的时候用make,指定len3和cap5,因此打印出来len为3、cap为5。此时注意我输出了切片各个元素,输出3个元素的时候正产输出,但第4个的时候报错了,可见len代表的就是我们能访问的数组个数。append后,len增加了1,但cap因为len并未大于cap,因此cap仍为5。

切片如何实现可变长

先看一段代码和输出就明白了

s := []int{}
for i := 0; i < 10; i++ {
   s = append(s, i)
   t.Log(len(s), cap(s))
}
打印结果
可以发现随着长度len的增长,容量cap也在增长。随着len要超过cap的时候cap会翻倍增长。

PS:看到这里也理解为什么切片增加元素的代码是s = append(s, i)这样写。按照感觉应该append(s, i)就可以,为什么前面还需要重新赋值。因为我们也看到了随着cap的增长,他的存储空间地址发生了变化,并不是在原有存储空间里增加元素。

值得注意的一点是,slice切片的内存自增长的代价,涉及到性能调优。

切⽚共享存储结构

切⽚共享存储结构
如何看待此图呢,所谓共享存储,比如图中Q2和summer切片,因为共享months切片的存储空间,修改任一方的元素,都会对另外一方造成影响。

还有一点需要注意:Q2截取了months切片中的下标4到7的元素,长度len为3,但cap是9;summer截取了months切片中的下标6到9的元素,长度len为3,但cap是7。

year := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep","Oct", "Nov", "Dec"}
Q2 := year[3:6]
t.Log(Q2, len(Q2), cap(Q2))
summer := year[5:8]
t.Log(summer, len(summer), cap(summer))
summer[0] = "Unknow"
t.Log(Q2)
t.Log(year)
打印结果
看打印结果可以发现,修改了summer中的一个元素后,无论是Q2还是months中的元素都发生了改变。

相关文章

  • Go之Slice(切片)

    内部结构 切片表面上用起来像是一个可变数组,但它其实是一个结构体,内部结构如下: 切片分为三个参数 指针,指向一片...

  • 【go笔记】切片(slice)结构的简介

    我们java里有个ArrayList, 那go有切片(slice)。看起来有点像,但是了解切片(slice)结构后...

  • 深入理解 Go Slice

    原文地址:深入理解 Go Slice 是什么 在 Go 中,Slice(切片)是抽象在 Array(数组)之上的特...

  • Go 切片(slice)

    Go中,数组的长度是不可变的,但是Go提供了一种灵活的内置类型:切片(也称为动态数组)。 切片的长度不固定,可以追...

  • 七、Go切片

    七、Go语言切片(Slice) Go 语言切片是对数组的抽象。 Go 数组的长度不可改变,在特定场景中这样的集合就...

  • go 语言切片

    go 语言切片 简单切片 slice 是 对 array 的一个 view 创建简单切片 切片作为函数参数 对切...

  • Go 基础篇之切片Slice

    今天开工第一天,2023 xdm 什么目标,评论区聊聊。今天我们来聊聊切片(Slice)。 1. 说在前面 在之前...

  • 七.Go切片slice

    切片slice 本身并不是数组,它指向底层的数组 作为变长数组的替代方案,可关联底层数组的局部或全部 数据类型为引...

  • Go语言切片(Slice)

    Go 语言切片是对数组的抽象。 Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,...

  • Golang之数组和切片

    引用 数组、字符串和切片 Go数组中的索引问题 深入解析 Go 中 Slice 底层实现 Golang 入门 : ...

网友评论

    本文标题:Go之Slice(切片)

    本文链接:https://www.haomeiwen.com/subject/mdcskctx.html