因为我是写php
的,刚开始写go
的时候老是被数组坑。因为在go
中的数组是固定长度,所以会存在越界的时候。而在go
中也很少直接使用数组。更多的时候会使用slice
(切片)。
数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。数组的长度是固定的。和数组对应的类型是Slice(切片),它是可以增长和收缩动态序列,slice功能也更灵活,但是要理解slice工作原理的话需要先理解数组。
数组的声明,需要指出数组内部元素类型,以及数组的长度
var name [len]type
如:声明一个长度为5的Int 类型数组
var numbers [5]int
数组元素的访问也是跟大多数语言一样,可以通过索引下标来访问,索引下标的范围是从0开始到数组长度减1的位置。内置的len函数将返回数组中元素的个数。 下面是一些数组的简单操作
func main() {var arr [3]int //声明一个长度为3的数组//往数组中增加元素arr[0] = 1arr[1] = 2arr[2] = 3// arr[3] = 1 这里就会产生错误//在声明数组的时候复制var addArr = [3]int{1, 2, 3}fmt.Println(addArr[0]) //moreArr := [...]int{1, 2} //这里...表示不确定长度。最终数组的长度由实际的元素个数确认fmt.Println(moreArr[0]) ////数组的使用for k, v := range arr {fmt.Printf("第%d个元素为%dn", k+1, v)}}
切片
slice是一个轻量级的数据结构,提供了访问数组子序列(或者全部)元素的功能,slice的底层引用了一个数组对象。一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址,要注意的是slice的第一个元素并不一定就是数组的第一个元素。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。
func main() {arr := [5]int{1, 2, 3, 4, 5} //定义一个数组sle1 := arr[0:2] //切片1sle2 := arr[1:3] //切片2sle1[0] = 9 //现在改变第一个切片的第一个元素fmt.Println(arr) //[9 2 3 4 5]fmt.Println(sle1) //[9 2]fmt.Println(sle2) //[2 3]/*** 现在改变两个切片共有的元素,通过结果可以看到* 底层数组 以及sle2中的一个元素都以及被改变了。* 可以很好的说明 切片是对数组的引用。两个切片实际引用的是同一个底层数组**/sle1[1] = 10fmt.Println(arr) //[9 10 3 4 5]fmt.Println(sle1) //[9 10]fmt.Println(sle2) //[10 3]}
上面的例子说明切片的第一个构成部分是指向底层数组的指针,下面来看看容量跟长度。内置的len和cap函数分别返回slice的长度和容量。
func main() {arr := [5]int{1, 2, 3, 4, 5}sli := arr[:4] // [1,2]fmt.Printf("切片长度为%d,容量为%dn", len(sli), cap(sli))//切片长度为4,容量为5sl2 := arr[:2] // [1,2]fmt.Printf("切片长度为%d,容量为%dn", len(sl2), cap(sl2)) //切片长度为2,容量为5sl3 := sli[:6] //这里会产生panic range of index。因为超过源切片的容量}
这里我们可以看到,如果切片操作超出cap(s)的上限将导致一个panic异常,但是超出len(s)则是意味着扩展了slice,因为新slice的长度会变大。那么我们应该怎么去给切片扩容呢,这里我们需要用到append
方法、看下面的例子
func main() {/*** 这里使用make 创建一个切片 * make([]T, len, cap) 其中cap可以省略。默认为Len*/sli := make([]int, 1, 1) fmt.Printf("切片长度为%d,容量为%dn", len(sli), cap(sli)) //2for i := 1; i < 5; i++ {sli = append(sli, 2)fmt.Printf("切片长度为%d,容量为%dn", len(sli), cap(sli)) //2}}输出结果切片长度为1,容量为1,地址为0xc00005a420切片长度为2,容量为2,地址为0xc00005a420切片长度为3,容量为4,地址为0xc00005a420切片长度为4,容量为4,地址为0xc00005a420切片长度为5,容量为8,地址为0xc00005a420
通过上面例子可以看出,当切片长度大于当前容量的时候,会为当前切片自动扩容。每次扩容的大小为当前容量的2倍,但是当容量超过1024之后每次扩容增量为四分之一
数组跟切片的基本就到这了。还没有入门,学习中。有错误的地方欢迎指出。
期待一起交流
如果觉得《位置2的索引超出数组范围不能超过10_golang学习笔记--切片slice 与数组 arr》对你有帮助,请点赞、收藏,并留下你的观点哦!