数组和切片
切片和数组的区别
1.数组的大小是固定的。
2.切片的底层虽然是数组,但可以随着元素的增多而自动扩大,但不会随着元素减少动态缩减。
3.切片可以看作是对数组的一层简单的封装,底层还是数组。因此切片类型是属于引用类型,引用类型还包括字典类型,通道类型,函数类型等。
数组是属于值类型。结构体,基础类型数据也属于值类型。
注意GO语言对于“传值和传引用”,只要根据被传递的值得类型判断就可以了。从传递的成本上来看,引用比值传递低很多
切片
切片的初始化主要分为用make创建,字面量创建和基于数组/切片创建。
1. s = make([]int,5,8)//创建一个长度为5,容量为8的切片
2. s=make([]int,5)//创建一个长度为5,容量也是5的切片
3. s=[]int{1,2,3,4}//创建一个长度为4,cap为4
s3 := []int{1,2,3,4,5,6,7,8}
s4 := s3[3:6]
fmt.Println(len(s3),cap(s3))
fmt.Println(len(s4),cap(s4))
这种方式的话要注意s4的容量其实是8 - 3 = 5,这个地方还是要注意的,
因为s3的底层数组的长度是8,s4是基于s3的,所以他们的底层数组是相同的,
也就是说s4可以扩展到s3的末尾。但通过s4是永远无法访问到s3前面的元素的。
切片容量的估算
-
一般情况下,新的切片会double一下cap。
-
如果原切片的长度大于1024,则以cap*1.25倍的增长
-
如果追加后的长度大于2倍的cap,则会以lenth为基准(通常会比lenth大一点)
切片的底层数组
切片的底层数组永远都不会被替换!!!!!
apend 返回的是新的切片,如果发生扩容指向的是新的数组,如果没有发生扩容,那么返回的是新的切片指向的是老的数组!!!!!!!!
s = make([]int,5)
s1 := append(s,1)
s1和s是完全不同的两个切片
package main
import "fmt"
func main() {
s3 := make([]int,5)
s5 := s3[0:3]
s4 := append(s3,4)//s4指向了不同的底层数组
s5 = append(s5,2) //s5指向的和s3一样的底层数组
s4[0] = 2//s4的变化不影响其它的
s5[0] = 3 //它会引起s3的变化
fmt.Println(s3[0])
}
思考题
1.如果多个切片指向同一个底层数组,那么注意什么?
一定要注意你的更改会影响到其它的切片的值!!!!!!!
2.怎么实现切片的缩容
新建数组,然后调用copy函数,然后让切片重新指向新的底层数组!
网友评论