Go学习:切片

创建Slice

切片(Slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型).这个片段可以是整个数组.

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	a := arr[2:6]
	fmt.Println("a =>", a) // a => [2 3 4 5]
	a0 := arr[:6]
	fmt.Println("a0 =>", a0) // a0 => [0 1 2 3 4 5]
	a1 := arr[2:]
	fmt.Println("a1 =>", a1) // a1 => [2 3 4 5 6 7]
	a2 := arr[:]
	fmt.Println("a2 =>", a2) // a2 => [0 1 2 3 4 5 6 7]
}

Slice属于半开半闭区间的,包头不包尾,:左右两边不写,相当于从下标0开始,到最后一个元素结束

slice作为参数

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	a1 := arr[2:]
	fmt.Println("a1 =>", a1) // a1 => [2 3 4 5 6 7]
	updateSlices(a1)
	fmt.Println("arr =>", arr) // arr => [0 1 100 3 4 5 6 7]
}
func updateSlices(s []int){
	s[0] = 100;
}
  • go语言一般不会使用数组作为参数,大多数情况下都是使用切片
  • Slice本身没有数据的,是对底层array的一个view.
  • 对Slice中元素的修改会影响array的元素

Reslice

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s := arr[2:]
	fmt.Println("s =>",s) // s => [2 3 4 5 6 7]
	s = s[:5]
	fmt.Println("s =>",s) // s => [2 3 4 5 6]
	s = s[:3]
	fmt.Println("s =>",s) // s => [2 3 4]
}
  • slice上面可以再建立slice
  • 这些不同的slice都是view的同一个array

Slice的扩展

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	fmt.Println("s1 =>",s1) // s1 => [2 3 4 5]
	s2 := s1[3:5]
	fmt.Println("s2 =>",s2) // s2 => [5 6]
}

在这里插入图片描述

  • s2把不属于s1的元素6也取出来了,说明Slice是可以进行扩展的,但是如果直接使用s1[4]还是会索引越界

Slice的实现

在这里插入图片描述

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	// s1 =[2 3 4 5], len(s1)=4, cap(s1)=6
	fmt.Printf("s1 =%v, len(s1)=%d, cap(s1)=%d\n",s1,len(s1),cap(s1))//
	s2 := s1[3:5]
	// s2 =[5 6], len(s2)=2, cap(s2)=3
	fmt.Printf("s2 =%v, len(s2)=%d, cap(s2)=%d\n",s2,len(s2),cap(s2))
	// panic: runtime error: slice bounds out of range [:4] with capacity 3
	fmt.Println(s2[:4])
}
  • Slice内部有三个变量

    • ptr指向Slice开头的元素
    • len是Slice的长度
    • cap是代表ptr到整个array最后
  • Slice可以向后扩展,不可以向前扩展

  • s[i]不可以超过len(s),向后扩展不可以超越底层数组cap(s)

Slice的操作

append

func main() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := arr[2:6]
	// s1 =[2 3 4 5], len(s1)=4, cap(s1)=6
	fmt.Printf("s1 =%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1))
	s2 := s1[3:5]
	// s2 =[5 6], len(s2)=2, cap(s2)=3
	fmt.Printf("s2 =%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2))
	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	fmt.Println("s3 =>", s3) // s3 => [5 6 10]
	fmt.Println("s4 =>", s4) // s4 => [5 6 10 11]
	fmt.Println("s5 =>", s5) // s5 => [5 6 10 11 12]
	fmt.Println("arr =>", arr) // arr => [0 1 2 3 4 5 6 10]
}
  • 添加元素时如果超越cap,系统会重新分配更大的底层数组(s4,s5不再是对arr的view,是系统分配更大的底层数组的view);原来的数组如果有引用,它就还在,如果没有引用就会被垃圾回收
  • 由于值传递的关系,必须接收append的返回值
  • s = append(s,val)

Slice的扩容

func printSlice(s []int){
	fmt.Printf("len=%d,cap=%d\n",len(s),cap(s))
}

func main() {
	var s [] int
	fmt.Println(s)
	for i:=0; i<10;i++{
		printSlice(s)
		s = append(s,i)
	}
	// [0 1 2 3 4 5 6 7 8 9]
	fmt.Println(s)
}
//len=0,cap=0
//len=1,cap=1
//len=2,cap=2
//len=3,cap=4
//len=4,cap=4
//len=5,cap=8
//len=6,cap=8
//len=7,cap=8
//len=8,cap=8
//len=9,cap=16

当len为0时,cap也为0,当len开始添加元素时,cap从开始扩容为1,以后每次添加不了元素时都进行2倍的扩容

func main() {
	s1 := []int{2,4,6,8}
	// [2 4 6 8] len=4,cap=4
	printSlice(s1)
	s2 := make([]int,16)
	// [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] len=16,cap=16
	printSlice(s2)
	// [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] len=16,cap=32
	s3 := make([]int, 16, 32)
	printSlice(s3)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

CopySlice

func main() {
	arr1 := []int{1,3,5,7,9}
	arr2 :=make([]int,10);
	// [0 0 0 0 0 0 0 0 0 0] len=10,cap=10
	printSlice(arr2)
	copy(arr2,arr1)
	// [1 3 5 7 9 0 0 0 0 0] len=10,cap=10
	printSlice(arr2)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除元素

删除中间的元素

func main() {
	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	arr1 = append(arr1[:1],arr1[2:]...)
	//[1 5 7 9] len=4,cap=5
	printSlice(arr1)

}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除头元素

func main() {
	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	head := arr1[0]
	arr1 = arr1[1:]
	//[3 5 7 9] len=4,cap=4
	printSlice(arr1)
	//head => 1
	fmt.Println("head =>",head)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除尾元素

func main() {

	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	tail := arr1[len(arr1)-1]
	arr1 = arr1[:len(arr1)-1]
	//[1 3 5 7] len=4,cap=5
	printSlice(arr1)
	//tail => 9
	fmt.Println("tail =>",tail)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.番茄炒蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值