Go相关知识储备(二)

Slice的学习:

切片是 Go 中的一种基本的数据结构,可以用来管理数据集合。

设计想法是由 动态数组 概念而来。为了开发者可以更加方便的使一个数据结构可以自动增加或者减少。但是切片本身并不是 动态数据 或者 数组指针。

切片常见的操作有 reslice、append、copy,切片还具有可索引、可迭代的优秀特性。

“冷”知识:

1. slice指向数组,对数组进行切片处理后,得到的结果地址和与之相对应的数组元素地址是相同的,共享数组的存储空间。

2. Go中的数组是值类型,赋值和函数传参都是值复制。

也正是因为这个特点,每次传参都需要数组被复制一遍,这样的话会耗费掉大量的内存,所以,函数传参用数组的指针最为合适。但是若传入了指针,对原数组的指针指向改变了,函数里面的指针都会改变。

切片的优势便体现出来,用切片传输数组参数,既可以节约内存,也可以合理处理好共享内存的问题。

切片是引用传递,所以它们不需要使用额外的内存并且比使用数组更有效率。

关于切片:

切片内部实现的数据结构是 通过指针引用底层数组,设定了相关属性将数据读写操作限定在指定的区域内。切片本身是一个只读对象,可以将它的工作机制看作类似于数组指针的一种封装。

切片实际上是对目标数组一个连续片段的引用,所以切片是一个引用类型(类似python里面的list类型)。这个片段可以是 整个数组 或是 由起始和终止索引标识截取的子集(左闭右开,右边索引对应的值不取),切片提供了一个指向数组的动态窗口。

小测试:

从go的内存地址中构造一个Slice:

make创建slice:

func makeslice(et *_type, len, cap int) slice {
	// 根据切片的数据类型,获取切片的最大容量
	maxElements := maxSliceCap(et.size)
    // 比较切片的长度,长度值域应该在[0,maxElements]之间
	if len < 0 || uintptr(len) > maxElements {
		panic(errorString("makeslice: len out of range"))
	}
    // 比较切片的容量,容量值域应该在[len,maxElements]之间
	if cap < len || uintptr(cap) > maxElements {
		panic(errorString("makeslice: cap out of range"))
	}
    // 根据切片的容量申请内存
	p := mallocgc(et.size*uintptr(cap), et, true)
    // 返回申请好内存的切片的首地址
	return slice{p, len, cap}
}

两种创建slice切片:

// 第一种 利用 make 创建 未定义初值
slice := make([]int, 4, 6)

// 第二种 利用 字面量 创建 可以赋予初值
slice := []int{10, 20, 30, 40}
// 注意:[] 中不要写内容,不然就变成了数组

切片扩容:

当一个切片的容量满了,就需要进行扩容了,怎么扩,策略是什么?

(扩容时的策略,扩容是生成全新的内存地址还是在原来的地址后追加)

扩容策略:

1. 首先判断,如果新申请的容量cap大于两倍的旧容量,那么最终容量就是新申请的容量

2. 如果新申请的容量cap并不大于两倍的旧容量,且旧切片的长度小于1024,那么最终容量是旧容量的两倍

3. 如果旧切片的长度大于等于1024,那么最终容量需要从旧容量开始循环增加原来的 四分之一 ,直到最终容量大于等于新申请容量

4. 最后如果最终容量计算值溢出,那么最终容量就是新申请容量

扩容安全:

其实分了两种情况

1. 当原数组还有容量可以直接进行扩容时,执行append操作后,会在原数组上直接操作,扩容以后的数组还是指向原来的数组,并没有新建一个新的数组。

因为扩容前后的数组都是同一个,所以这也就导致了新的切片修改了一个值,就影响到了老的切片,甚至影响到了原数组。

**************在用字面量创建切片的时候,cap的值一定要保持清醒**************

2. 当原数组的长度 等于 容量,也就是容量到达了最大值时,再想扩容,Go默认会先开一片内存区域,把原有的值拷贝过来,再执行append()操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值