Go slice原理分析

slice原理分析

slice也称动态数组

	make格式创建
	s1 := make([]int,12) // 指定长度
	s2 := make([]int,10,100) // 指定长度len和容量cap
	字面量形式
	s3 := []int{} // 需要注意空切片其值不是nil
	s4 := []int{1,2,3} // 长度为3的切片
	从数组或者切片中截取切片
	arr := [5]int{1, 2, 3, 4, 5}
	s5 := arr[0:2] // 左闭右开
	s6 := s5[0:1]  // 从切片中切取

需要特别注意的是,如果修改切片中的元素,会递归影响从原数组或者切片

	再提一点,使用new函数创建切片
	s7 := *new([]int)
	此时创建的切片的值为nil

关于切片的操作

	s := make([]int, 0)
	fmt.Println(len(s), cap(s))
	fmt.Printf("%p\n", s)
	s = append(s, 1)
	fmt.Printf("%p\n", s)
	s = append(s, 2, 3, 4)
	fmt.Printf("%p\n", s)
	s = append(s, []int{5, 6}...)
	fmt.Printf("%p\n", s)
	fmt.Println(s)
	
	0 0
	0x118f390
	0xc000124020
	0xc000126020
	0xc000132000
	[1 2 3 4 5 6]

可以看到每操作一次append都是新建一个切片,然后把原切片的内容复制过去,然后返回新的切片

直接来看slice的数据结构

	type slice struct {
		array unsafe.Pointer 	// 指针指向切片在内存中的起始地址
		len   int				// 长度
		cap   int				// 容量
	}

前面也提到使用数组来构建切片,下面可以证明数组和数组的切片共享底层存储空间

	array := [10]int{}
	slice := array[5:7]
	fmt.Println(len(slice), cap(slice))
	2 5

关于slice扩容机制,涉及内存分配原则:

  1. 原slice的容量小于1024,新切片的容量将扩大到原来的2倍
  2. 原slice的容量大于1024,新切片的容量将扩大到原来的1.25倍

这么做有以下两点好处:

  1. 当切片容量较小时,采用较大的扩容倍速,可以避免频繁扩容,减少内存分配的次数和数据拷贝的代价,这里会涉及到元素的搬迁,费时费空间。
  2. 当切片容量较大时,采用较小的扩容倍速,可以有效避免内存空间的浪费。

扩容的步骤:先将slice扩容,得到新的slice,再将新元素追加到新slice中,返回新的slice。

切片表达式
a[low : high]
a[low : high : max] // 这里的max将限定切片的容量为 max-low, low可以省略,而high和max不可以省略
low和high的最大值应为切片的容量

这里有会引伸出一个问题,对于扩展表达式,向限制最大容量的切片中append元素,如果容量不够那么会产生一个新的切片,而不是覆盖原始的数组或切片。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hewesH

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

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

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

打赏作者

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

抵扣说明:

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

余额充值