当前位置:   article > 正文

golang切片简介_golang 切片

golang 切片

目录

创建

创建与初始化

make函数创建

初始化创建

空切片与nil

创建共享底层数组的切片

访问

迭代

不定参数传递

操作

扩容

插入元素

尾部插入

头部插入

中间插入

删除元素

尾部删除

头部删除

中间删除

遍历时删除


切片(slice)是Golang中数组之上的抽象;可按需自动增长与缩小。切片的底层是连续的内存块。

创建

切片本身是一个三个字段的数据结构:

  • Data:指向底层数组的指针;
  • Len:切片中元素的个数;len(s)获取;
  • Cap:切片的容量(不需重新分配内存前,可容纳的元素数量);cap(s)获取;
  1. type SliceHeader struct {
  2.     Data uintptr
  3.     Len  int
  4.     Cap  int
  5. }

创建与初始化

有多种创建切片的方式。

make函数创建

内置的make函数可用于创建切片(长度不能超过容量):

  1. // 创建长度为0,容量为10的切片
  2. s := make([]int010)
  3. // 创建长度为10(存储的是对应类型的默认值,即0),容量为10的切片
  4. s2 := make([]int10)
  5. // 获取底层对应数据结构
  6. low:=(*reflect.SliceHeader)(unsafe.Pointer(&s1))
  7. fmt.Printf("Data:%d,Len:%d,Cap:%d\n",low.Data,low.Len,low.Cap)

初始化创建

根据给定的数据,自动创建并初始化切片(与数组的区别是[]中没有长度信息):

  1. // 长度、容量都为3的切片
  2. s := []int{1,2,3}
  3. // 长度、容量都为10,最后一个元素为99,其他为默认值0
  4. s2 := []int{999}

空切片与nil

声明时不做任何初始化就会创建一个nil切片;而空切片是底层数组包含0个元素,且没有分配存储空间。nil与空切片都可直接获取长度(len)或追加元素(append)。

  1. // 值为nil的切片
  2. var s []int
  3. // 创建空切片
  4. s1 := make([]int0)
  5. s2 := []int{}

创建共享底层数组的切片

在已有数组/切片上创建切片为:s = src[low : high : max] ,三个参数意义为

  • low为截取的起始下标(含), high为窃取的结束下标(不含high),max为切片保留的原切片的最大下标(不含max);
  • 新切片从老切片的low下标元素开始,len = high - low, cap = max - low;high 和 max一旦超出在老切片中越界,就会发生runtime err,slice out of range。
  • 没有指定max:max的值为截取对象(数组、切片)的容量。

在已有数组/切片上切出一部分可以生成新的切片,他们共享底层的数组;因此修改一个切片的内容(在不扩容的情况下),会影响到其他共享底层数组的切片:

  1. // 元素范围为[i,j),k限制容量为(k-i)
  2. s := src[i:j:k]
  3. // 从i到尾部
  4. s := src[i:]
  5. // 从头到j(不包括j)
  6. s := src[:j]
  7. // 从头到尾(复制整个切片),但底层数组还是公用的
  8. s := src[:]

访问

切片只能访问其长度范围内的内容,通过下标访问

  1. s[i] = 10
  2. = s[i]

迭代

切片是一个集合,可以通过range迭代其中的元素:

  1. for index, value := range myS{
  2.     fmt.Printf("index: %d, value: %d\n"index, value)
  3. }

range返回的第二个值是对应元素的一份副本,不能用于修改;若要修改则需要通过索引:

  1. for index, _ := range myS{
  2.     myS[index+= 1
  3. }

迭代方式遍历时,不能有其他线程对切片进行操作(添加、或删除元素),否则会引发恐慌。

不定参数传递

切片可直接传递给‘不定参数’,即使空切片也可以:

  1. func NilSliceParam() {
  2. var s []string
  3. multiEle(s...)
  4. }
  5. func multiEle(all ...string) {
  6. log.Println(all)
  7. }

操作

通过函数append可在切片尾部追加元素;通过copy(dest,src)可复制切片,复制的长度是minimum of len(src) and len(dst)。

可对nil切片追加元素,以及求长度:

  1. var sl []int // nil
  2. if sl == nil{ // true
  3. fmt.Println("is nill")
  4. }
  5. fmt.Println(sl) // []
  6. fmt.Println(len(sl)) // 0
  7. sl = append(sl, 1) // [1]

扩容

Slice依托数组实现,底层数组容量不足时可自动重新分配。追加数据通过append(返回值一定要再赋值给原slice);容量不足时会自动扩容:

  • <1024时,扩大为原来2倍;
  • >=1024时,扩大为原来的1.25倍;
  1.     var s []int // s == nil
  2.     fmt.Println(s) // []
  3.     fmt.Println(len(s)) // 0
  4.     for i := 0; i < 5; i++ {
  5.         s = append(s, i+1)
  6.     }
  7.     // 容量:0,1,2,4,8

插入元素

尾部插入

在插入元素时,若空间不足则会自动重新分配新的空间:

  1. = append(a, 123)
  2. = append(a, []int{1,2,3}...) // 追加切片时,需要使用...解包

头部插入

头部插入时,会引起内存的分配与复制操作:

  1. // 即使一个元素,也要以切片的形式插入
  2. = append([]int{1}, a...)
  3. = append([]int{1,2,3}, a...)

中间插入

在中间(i)插入元素:

  • 先通过append增长空间;
  • 使用copy移动后面元素;
  • 插入元素到指定位置
  1. = append(a, x...)        // 先扩展出足够的空间
  2. copy(a[i+len(x):], a[i:])  // 后移len(x)个元素,空出空间
  3. copy(a[i:], x)

删除元素

从切片中删除的元素若是指针(特别是尾部删除时,可能还会被底层数组引用中,从而无法被gc回收);为了能及时的释放,在需要在删除前,先把对应元素设置为nil再删除;

  1. a[len(a)-1]=nil
  2. = a[:len(a)-1]

尾部删除

删除尾部N个元素:

a = a[:len(a)-N]

头部删除

删除头部元素有两种方式:

  • 改变数据指针(直接通过切片操作即可)
  • 不改变数据指针(移动元素)
  1. // 删除头部N个元素,改变数据指针
  2. = a[N:]
  3. // 删除切片头部元素,不改变数据指针:
  4. = append(a[:0], a[N:]...)  // 在头部追加剩余元素
  5. = a[:copy(a, a[N:])]       // 复制元素都头部,然后修改切片长度

中间删除

删除切片中间部分元素:

  1. // 方法1:append追加,覆盖被删除元素
  2. = append(a[:i], a[i+N:]...)
  3. // 方法2:复制,覆盖被删除元素
  4. = a[:i+copy(a[i:], a[i+N:])]

遍历时删除

要在遍历时删除,就不能用range迭代的方式:

  1. func removeAllLessEle(queueMax []int, ele int) []int {
  2. // pop all ele less than ele
  3. for j := 0; j < len(queueMax); {
  4. if queueMax[j] < ele {
  5. queueMax = append(queueMax[:j], queueMax[j+1:]...)
  6. } else{
  7. j = j + 1
  8. }
  9. }
  10. return queueMax
  11. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/206393
推荐阅读
相关标签
  

闽ICP备14008679号