失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > golang中的slice

golang中的slice

时间:2023-12-19 07:55:46

相关推荐

golang中的slice

golang中的slice表示一个可变长度的数组,声明为[]T,其中T是类型。 关于数组请参见:golang中的数组

slice跟数组紧密相连,slice有三个属性,分别是:指针、长度(len)和容量(cap),其中指针指向底层数组,所以它天然依赖底层数组。从某种意义上来讲,slice更像一个结构体,这个结构体里面必然包含一个指针。

slice的指针指向底层数组

arr := [...]int{1, 2, 3, 4, 5}slice1 := arr[:3]for i := range slice1 {slice1[i]++}fmt.Println(slice1)//[2 3 4]fmt.Println(arr)//[2 3 4 4 5]

对slice中的元素的值加一,影响到了数组arr中的值,因为 arr就是slice1的底层数组,slice1中的指针指向arr。

如果对字符串(等同于[]byte)使用x[m:m],返回的还是一个字符串(其实还是一个[]byte),但如果对数组使用x[m:m],返回的就不是数组了,而是slice。

注意一下初始化数组和初始化slice的方式

// 初始化数组,编译器会自动解析数组长度arr := [...]int{1, 2, 3, 4, 5}// 初始化slice,没有指定长度。golang会创建一个固定长度的底层数组,并用slice指向它slice := []int{1, 2, 3, 4, 5}

slice的可比较性

slice之间无法直接比较,因为slice的本质是一个固定范围的指针,并不是直接的元素,并且底层数组还有可能会改变。

不过,slice可以和nil作对比。

if slice == nil {}

slice的零值

nil是slice的零值,它的没有底层数组,len为0,cap为0。

var s []int // len(s) == 0, s == nils = []int(nil) // len(s) == 0, s== nils = []int{}// len(s) == 0, s != nil

所以检查一个slice是否为空,应该使用len(s) == 0, 而不是与nil作比较。

当s为nil时,len(s)也是安全的,返回0。

使用make创建slice

make([]T, len)make([]T, len, cap)

如果我们一开始就知道要创建多长的slice,例如长度为x,那么这样写会更高效,因为可以避免在后续的append中重新创建底层数组。

make([]T, 0, x)

append 函数

append([]T x, T y)

append的实现原理是,先检查当前slice是否有足够的容量,如果有,则定义一个新的slice,和之前的slice指向相同的底层数组,然后将新元素复制到新slice的新位置,并返回新slice。如果容量不足,则创建一个容量更大的slice(按照某种算法扩大容量),同时也会创建一个新的底层数组,将原slice的值复制过来,再将新元素复制到新slice的新位置。

所以,append每次都会返回一个新的slice,但我们无法确定旧slice和新slice是否指向同一个底层数组。

因此,使用append函数的正确姿势是

slice = append(slice, item)

实际上,我们对任何可能会生成新slice的函数,都要再把返回值赋给原变量。

slice的本质

slice的本质是一段固定范围的指针,append函数会改变slice的长度(len),所以需要返回一个新的slice。这么看来,slice并不像是严格意义上引用类型,更像是一种聚合类型

type IntSlice struct {ptr*intlen, cap int}

如果觉得《golang中的slice》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
golang——slice避坑

golang——slice避坑

2019-10-30

golang slice 详解

golang slice 详解

2021-05-20

golang slice扩容

golang slice扩容

2018-08-08

golang slice如何拷贝

golang slice如何拷贝

2021-07-24