数组与切片

yc90s · · 862 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

[原文链接](https://yc90s.github.io/2017/11/20/%E6%95%B0%E7%BB%84%E4%B8%8E%E5%88%87%E7%89%87/) ##数组 ### 定义 数组是一组同类型数据的集合,它是**值类型**,通过从0开始的下标索引访问元素值。初始化后**数组长度是固定的**,无法修改其长度。当作为方法的入参传入时將复制一份数组而不是引用同一指针。数组的长度也是其类型的一部分。 ### 初始化 - 长度为5的数组,其元素值依次为:1, 2, 3, 4, 5 ``` [5]int{1, 2, 3, 4, 5} ``` - 长度为5的数组,其元素值依次为:1, 2, 0, 0, 0. 在初始化时没有指定初值的元素將会赋值为其元素类型的默认值,int是0,string是““ ``` [5]int{1, 2} ``` - 长度为5的数组,其长度是根据初始化时指定的元素个数决定的 ``` [...]int{1, 2, 3, 4, 5} ``` - 长度为5的数组,其元素值依次为:0, 0, 1, 2, 3. 在初始化时指定了2, 3, 4索引中对应的值:1, 2, 3 ``` [5]int{2:1, 3:2, 4:3} ``` - 长度为5的数组,其元素值为:0, 0, 1, 0, 3. 由于指定了最大索引4对应的值为3, 根据初始化的元素个数确定其长度为5 ``` [...]int{2:1, 4:3} ``` ## 切片 ### 定义 切片基于数组构建,但是提供更强的功能。切片的存储结构依次是底层数组的指针、切片长度、切片容量、切片数据。切片长度是指已经被赋过值的最大下标+1, 可通过len()获取。容量是指切片目前可容纳的最多元素个数,可通过cap()获取。**切片是引用类型**,而且**切片的长度和容量可以修改**,当切片的容量发生变化时,可能会重新分配内存,**使得切片和原底层数组的关联断开** ### 初始化 - 直接初始化,[]表示是切片类型,初始化值依次是1, 2, 3. 其cap=len=3 ``` s := []int{1, 2, 3} ``` - 通过数组或其它切片初始化,是其的引用 ``` s := arr[startIndex:endIndex] ``` - 通过make()初始化,可指定len和cap ``` s := make([]int, len, cap) ``` 切片重新分配内存,导致切片和原底层数组关联断开的情况需要特殊注意,考虑如下代码: ``` arr1 := [3]int{1, 2, 3} arr2 := [3]int{1, 2, 3} sli1 := arr1[:1] sli2 := arr2[:1] sli1[0] = 0 sli2[0] = 0 sli1 = append(sli1, 5) sli2 = append(sli2, 5, 5, 5) fmt.Println("arr1: ", arr1) fmt.Println("arr2: ", arr2) fmt.Println("sli1: ", sli1) fmt.Println("sli2: ", sli2) ``` 执行后的输出结果是 > arr1: [0 5 3] > arr2: [0 2 3] > sli1: [0 5] > sli2: [0 5 5 5] 对切片sli1的append操作实际并没有重新分配内存,它还是原数组的引用,所以对sli1的append操作仍而应用到了数组arr1上;而对切片sli2的append操作,重新分配了内存,使得它和原数组的关联断开了,所以对sli2的append操作并没有影响到数组arr2 ## 数组与切片区别 ### 数组长度不可变,切片长度和容量都可变 数组的长度在初始化时就会确定下来,而切片的长度可以动态变化 ### 数组是值类型,而切片是引用类型 用一段代码说明一下 ``` func testArr(arg [3]int) { arg[0] = 0 fmt.Println("testArr: ", arg) } func testSli(arg []int) { if len(arg) == 0 { arg = append(arg, 0) } else { arg[0] = 0 } fmt.Println("testSli: ", arg) } func main() { arr := [3]int{1, 2, 3} fmt.Println("before testArr(): ", arr) testArr(arr) fmt.Println("after testArr(): ", arr) sli := arr[:] fmt.Println("befor testSli(): ", sli) testSli(sli) fmt.Println("after testSli(): ", sli) } ``` 执行后程序输出 > before testArr(): [1 2 3] > testArr: [0 2 3] > after testArr(): [1 2 3] > befor testSli(): [1 2 3] > testSli: [0 2 3] > after testSli(): [0 2 3] testArr()函数对传进去的arr参数的修改,并没有对arr变量生效,而testSli()函数对sli变量的修改写回到了sli变量

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

862 次点击  
加入收藏 微博
下一篇:golang API
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传