ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go语言切片Slice的使用

2022-06-13 22:34:33  阅读:147  来源: 互联网

标签:Slice fmt 切片 Println Sprintf 数组 Go main s1


1、来源于数组的切片

package main

import "fmt"

func main() {
   a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //添加了...表示数组
   b := a[2:6]                           //切片
   fmt.Println(b)                        //[3 4 5 6] 左包右不包
}

可以省略开始,可以省略结束,可以省略开始和结束

package main

import "fmt"

func main() {
   a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组
   b := a[2:6]                           //切片
   fmt.Println(b)                        //[3 4 5 6] 左包右不包
   c := a[:6]                            //可以省略开始
   fmt.Println(c)                        //[1 2 3 4 5 6]
   d := a[2:]                            //可以省略结束
   fmt.Println(d)                        //[3 4 5 6 7 8]
   e := a[:]                             //可以省略开始和结束
   fmt.Println(e)                        //[1 2 3 4 5 6 7 8]
}

2、切片slice是数组的视图

改变切片的元素,底层数组也会改变

package main

import "fmt"

func update(a []int) {
	a[0] = 100
	a[1] = 1000
}

func main() {
	a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组
	b := a[2:6]                           //切片是数组的视图  查看数组的第2到第6个元素
	fmt.Println(b)                        //[3 4 5 6] 左包右不包

	src := a[:] //底层数组a的全部视图
	fmt.Println(fmt.Sprintf("原始的底层数组全视图是:%d", src))
	update(src)
	fmt.Println(fmt.Sprintf("改变了切片后的底层数组全视图是:%d", src))
	fmt.Println(fmt.Sprintf("原始的底层数组是:%d", a))
}

3、slice可以继续reslice

package main

import "fmt"

func update(a []int) {
   a[0] = 100
   a[1] = 1000
}

func main() {
   a := []int{1, 2, 3, 4, 5, 6, 7, 8} //[]中没有...代表切片
   b := a[2:7]                        //切片可以再次切片,称为reslice
   fmt.Println(b)                     //[3 4 5 6 7]
   c := b[3:]
   fmt.Println(c) //[6 7]
   d := c[:1]
   fmt.Println(d) //[6]
}

4、slice会向底层看齐

如果切片时,切片到头了,则会向底层查看一下是否还有可视的值,因为切片是数组的视图,所以最终会视图到最底层的数组,例如

package main

import "fmt"

func main() {
   arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
   fmt.Println(fmt.Sprintf("底层数组:%d", arr))
   s1 := arr[2:6]
   fmt.Println(fmt.Sprintf("arr[2:6]:%d", s1))
   // s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢
   s2 := s1[3:5]
   fmt.Println(fmt.Sprintf("s1[3:5]:%d", s2))
   //会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr
}

可以看出s1都没有s1[4]而s2取出来了7,这是由于视图向下看,看到了底层数组的7

说明:

数组arr是1,2,3,4,5,6,7,8

s1 := arr[2:6] 是取数组的第三个元素,总共取4个元素,就是3,4,5,6,但是s1是知道数组arr还有7,8两个元素,因为s1是数组的视图

s2 := s1[3:5]是取s1的第四个元素,总共去2个元素,第一个元素就是6,但是第二个元素在s2中没有了,如果打印s2[4]则会报错,但是因为是视图,s1是知道后面的元素是7,8,因此第二个元素就可以取到7,如果再取一个元素,那就是可以取到8,如果再取一个,因为底层数组到8便没有了,因此抛出异常

5、切片slice的底层数据结构

image-20220612204917905

说明

①slice由ptr和len以及cap组成

ptr是指针,指向切片的第一个元素

len是切片的长度,从ptr开始到结束的元素个数,当下标 超过这个长度后会报下标越界的错误

cap表示切片的容量,表示共可以存多少个元素,当添加元素后,如果容量不够,会自动扩容

⑤slice可以向后扩展,不可以向前扩展,扩展可以超过len的值,但不能超过底层数组的cap

打印切片的len和cap

package main

import "fmt"

func main() {
   arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
   fmt.Println(fmt.Sprintf("底层数组:%d", arr))
   s1 := arr[2:6]
   fmt.Println(fmt.Sprintf("arr[2:6]:%d, len:%d, cap:%d", s1, len(s1), cap(s1)))
   // s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢
   s2 := s1[3:5]
   fmt.Println(fmt.Sprintf("s1[3:5]:%d, len:%d, cap:%d", s2, len(s2), cap(s2)))
   //会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr
}

image-20220613213005155

6、slice添加元素

使用append添加元素,添加的元素会紧跟在后面,添加后多余cap的数据会被挤出去

append方式作用于底层数组

package main

import "fmt"

func main() {
   arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
   fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 6 7]
   s1 := arr[2:6]
   fmt.Println(fmt.Sprintf("s1:%d", s1)) //[2 3 4 5]
   s2 := s1[3:4]
   fmt.Println(fmt.Sprintf("s2:%d", s2)) //[5]
   s3 := append(s2, 10)
   fmt.Println(fmt.Sprintf("s3:%d", s3)) //[5 10]
   // 由于s2是[5] append后10直接跟着5后面,把6给直接顶掉了
   //因为slice是底层数组的view,即是底层数组的视图,所以append作用于底层数组
   //底层中的5后面的数6就被10给替换了
   fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 7]

   s4 := append(s3, 11) //[5 10 11]
   fmt.Println(fmt.Sprintf("s4:%d", s4))
   //由于s3是[5 10],直接append一个11,因此11直接跟在10后面,原来底层数组10后面是7,因此把7给替换成了11
   fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 11]

   s5 := append(s4, 12) //[5 10 11 12]
   fmt.Println(fmt.Sprintf("s5:%d", s5))
   //由于s4是[5 10 11]直接append一个12,因此12直接跟在11后面,但是由于再跟一个12,就超过了底层数组的cap,因此会产生一个新的地址存放新的数据
   //如果用debug的方式查看,就能看到产生了新的地址存放新的数组
   fmt.Println(fmt.Sprintf("底层数组:%d", arr))
}

debug方式查看新的地址存放新数据

image-20220613220521434

7、slice的几种创建方式

  • var定义slice
package main

import "fmt"

func main() {
   var s []int//申明切片s,默认是nil
   fmt.Println(fmt.Sprintf("var 定义的 slice默认值:%v", s))
   for i := 0; i < 100; i++ {
      s = append(s, i)//通过append方式添加元素
      fmt.Println(fmt.Sprintf("len:%d cap:%d, value:%d", len(s), cap(s), s))
   }
   //可以看到cap会默认自己扩张

}
  • 冒号:定义slice
package main

import "fmt"

func main() {
   s := []int{2, 4, 6, 8, 10}
   fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s))
}
  • make关键字创建slice

如果想创建某个长度的slice可以使用make函数

例如:我想创建cap为10的slice,但我只知道其中5个

package main

import "fmt"

func main() {
	s := make([]int, 5, 10)
	s[0] = 10
	s[1] = 1
	s[2] = 10
	s[3] = 1
	s[4] = 10
	fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s))
}
  • copy关键字创建slice
package main

import "fmt"

func main() {
   s := []int{1, 2, 3, 5}
   fmt.Println(s)
   s1 := []int{0, 0, 0}//[1 2 3 5] [1 2 3]
   copy(s1, s)
   fmt.Println(s, s1)
}

8、删除slice元素

删除中间的元素

package main

import "fmt"

func main() {
   s := []int{1, 2, 3, 4, 5}
   fmt.Println(s)
   s1 := append(s[:2], s[3:]...)//移除3
   fmt.Println(s1)
}

删除首元素

package main

import "fmt"

func main() {
   s := []int{1, 2, 3, 4, 5}
   fmt.Println(s)
   s1 := s[1:]
   fmt.Println(s1)
}

删除尾巴元素

package main

import (
   "fmt"
)

func main() {
   s := []int{1, 2, 3, 4, 5}
   fmt.Println(s)
   s1 := s[:len(s)-1]
   fmt.Println(s1)
}

标签:Slice,fmt,切片,Println,Sprintf,数组,Go,main,s1
来源: https://www.cnblogs.com/rainbow-tan/p/16372568.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有