go 数据结构底层原理
array底层原理
go中的数组是由固定长度的特定类型元素组成的序列,数组的长度是数据类型的组成方式,所以不同长度和不同类型的元素组成的数组是不同的数组类型。数组属于值类型,因此在复制或者传递参数时,会对整个数组内容进行复制,所以在调用的函数中修改数组的值不会影响到原来的数组的值。此外由于需要复制整个数组的内容,如果数组太大会导致复制成本太大, 所以可以传递数组的指针。
Slice底层原理
简单的将,切片是一种简化版的动态数组。切片的在go中的定义为如下,在对切片赋值,就是修改指向数组的指针,len,cap的值。而在拷贝的时候,如果直接使用=,则会复制被拷贝的切片的数组指针,cap,len值,因此会指向同一个地址,而使用copy的话会把被拷贝的切片中的数组的值复制到拷贝的切片的数组中。即地址是不同的。
type SliceHeader struct{
Data uintptr
Len int
Cap int
}
Data可以简单看做指向了底层数组(其实其中Data保存了底层数组的指针的值,可以进行指针计算从而得到其他值,然后转变为Pointer,再转变为对应类型的指针进行访问。(uintptr不等于指针,只存储了底层数组的值,参考uintprt和pointer的区别))。len代表可以访问的长度,而Cap则是底层数组的容量(由可访问的第一个元素到底层数组末尾的长度),显然cap>=len,所以如果使用划分的方式的得到新切片时,如果从前面阶段,会导致cap减少,而从后面cap不会变.
a:=[]int{
1,2,3,4,5} //len=5,cap=5
b:=a[1:3]//{2,3},len=2,cap=4
c:=a[:4]//{1,2,3,4},len=4,cap=5
Slice属于引用类型,简单来讲就是在调用函数中修改了slice中的值会影响到原来的切片中的值。因为golang是一个值传递的语言,在函数调用时候传递的参数时拷贝的副本。由上述复制原理可知,这里使用的是浅拷贝,及会把切片的值(指针,cap,len)复制一份,以此可以通过这个指针直接改变原切片的值,