数组和Slice(切片)
数组
数组是固定长度相同类型的集合。数组的长度必须是一个常量表达式(编译阶段就知道结果),数组元素的值可以由地址下标访问和修改的。
数组是比较特殊的类型,数组的长度是数组类型的一部分,像[3]int
和[6]int
二者是不同类型
var a [3]int
var b []string
var c = [5]int{1, 2, 15, 23, 16}
var d = [...]int{9, 6, 7, 5, 12} // `...`可以替代写具体长度,编译器可以帮你算
数组遍历
数组可以使用for
和for range
方式来遍历
var arr = [9]int{0, 1}
for i := 0; i < len(arr); i++ {
arr[i] = i * 2
}
for _, v := range arr {
fmt.Println(v)
}
for i, _ := range arr {
fmt.Println(arr[i])
}
数组在golang中实践使用的比较少,很多场景中我们都使用Slice
来替代。
切片(slice)
切片是对数组一段连续内存的引用,在golang中Slice的底层结构为
type SliceHeader struct {
Data uintptr //指向该切片的索引的底层数组中的起始位置
Len int //切片长度
Cap int //切片总容量
}
内置函数len
和cap
可以分别获取切片的长度和大小。
切片的内存模型
var a=[5]int{1,2,3,4,5}
b:=a[0:3] // b SliceHeader{&a[0],3,5}
c:=a[3:5]// c SliceHeader{&a[3],2,2}
切片表达式
var a=[5]int{1,2,3,4,5}
b:=a[:3] //等同于 a[0:3]
c:=a[3:] //等同于 a[3:5]
d:=a[:] //等同于 a[0:5]
使用make 创建
a := make([]int, 8, 9) //创建[]int且切片 len为8 cap为9
aa := make([]int, 8) //参数cap可以省略 默认cap和len一样
切片的复制
golang内置函数copy
来复制切片
copy
的声明格式func copy(dist []T,src []T)int
,copy的返回值为拷贝的长度
src1 := []int{1, 2, 3}
src2 := []int{4, 5}
dest := make([]int, 5)
n := copy(dest, src1) //注意这边只拷贝了前三个元素
n = copy(dest[3:], src2) //拷贝从第四个位置上
切片追加
golang内置函数append
来追加切片。
append
声明格式func append(dest[]T, x ...T) []T
append
方法将多个具有相同类型的元素追加到dest
切片后面并且返回新的切片,追加的元素必须和dest
切片的元素同类型。
如果dest
的切片容量不够,append
会分配新的内存来保证已有切片元素和新增元素的存储。因此返回的切片所指向的底层数组可能和dest
所指向的底层数组不相同。
a := []int{1, 2, 3} //a len:2 cap:3
b = append(a, 4, 5, 6) //b: len:5 cap:5 b和a指向的数组已经不同
c := append(a,b...) // 使用...快速展开b
切片遍历
切片遍历和数组基本上没差别
var arr = make([]int,10)
for i := 0; i < len(arr); i++ {
arr[i] = i * 2
}
for _, v := range arr {
fmt.Println(v)
}
for i, _ := range arr {
fmt.Println(arr[i])
}