golang中的数组和切片 关于slice和array共用空间的问题

package main

import "fmt"

func main(){
	//var array [10]int
	array := make([]int,10)
	array = append(array,1,2,3,4,5,6,7,8,9,10)
	var slice = array[5:6]
	fmt.Println("slice的长度是",len(slice))
	fmt.Println("slice的cap是",cap(slice))

	fmt.Println(array)
	fmt.Println(slice)

}

输出如下:

slice的长度是 1
slice的cap是 15
[0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10]
[0]

我们发现虽然,var slice = array[5:6],以为slice的cap是1,但是实际上slice的cap是15,也就是从5开始。

切片的底层如下,

也就是说,数组后面的内容都作为切片的预留内存,即他的capacity为从初始的位置到array结束的地方。

数组和数组的切片共享底层的存储空间,这事使用的过程中需要额外注意的地方。

查看源码包中的,slice是一个结构体,他的array指针指向底层的数组。

type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

1)使用make来创建slice

这个时候,可以同时指定长度和容量,创建的时候底层会分配一个数组,数组的长度就是他的容量。

slice := make([]int,5,10)

 该slice的长度为5,即可以使用下标 slice[0] ~ slice[4]来操作里面的元素,capacity为 10,表示后续向slice添加新的元素时可以不必重新分配内存,直接使用预留内存即可,直到预留内存不足时再扩容。

2)使用数组来创建slice

使用数组创建slice时,slice将与原数组共用一部分内存。
例如,slice := array [5:7]语句所创建的slice的结构如下图所示。

 切片从数组 array[5]开始,到数组 array[7]结束(不含 array[7]),即切片的长度为2,数组后面的内容都作为切片的预留内存,即capacity 为5。
数组和数组的切片共享底层存储空间,这是使用过程中需要额外注意的地方。

3 ) slice扩容


使用 append向slice追加元素时,如果slice空间不足,则会触发slice扩容,扩容实际上是重新分配一块更大的内存,将原 slice的数据拷贝进新slice,然后返回新slice,扩容后再将数据追加进去。
例如,当向一个 capacity为5且length也为5的slice再次追加1个元素时,就会发生扩容,如下图所示。

 案例如下:

func main(){
	//var array [10]int
	array := make([]int,10)
	fmt.Println("扩容前的array",array)
	fmt.Println("扩容前的array的len",len(array))
	fmt.Println("扩容前的array的len",cap(array))
	array = append(array,1,2,3,4,5,6,7,8,9,10)
	fmt.Println("扩容后的array",array)
	fmt.Println("扩容后的array的len",len(array))
	fmt.Println("扩容后的array的cap",cap(array))
}
扩容前的array [0 0 0 0 0 0 0 0 0 0]
扩容前的array的len 10
扩容前的array的len 10
扩容后的array [0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10]
扩容后的array的len 20
扩容后的array的cap 20

扩容操作只关心容量,会把原slice的数据拷贝到新slice中,追加数据由append在扩容结束后完成。由上图可见,扩容后新slice的长度仍然是5,但容量由5提升到了10,原slice的数据也都拷贝到了新slice指向的数组中。


4) slice拷贝


使用copy()内置函数拷贝两个切片时,会将源切片的数据逐个拷贝到目的切片指向的数组中,拷贝数量取两个切片长度的最小值。
例如长度为10的切片拷贝到长度为5的切片中时,将拷贝5个元素。也就是说,拷贝过程中不会发生扩容。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值