1.Golang中的数组

数组是一种具有固定长度的基本数据结构,在golang中与C语言一样数组一旦创建了它的长度就不允许改变,数组的空余位置用0填补,不允许数组越界。

数组的一些基本操作:

1.创建数组:

func main() {
var arr1 = [...]int{1,2,3,4} //[...]默认为元素的数量即为数组的长度
fmt.Println(len(arr1)) //4
arr1[4] = 5 //panic 数组越界
fmt.Println(arr1)
var arr2 = [10]int{1,2,3,4}
fmt.Println(arr2) //[1 2 3 4 0 0 0 0 0 0]
}

  2.数组是值拷贝传递:

func main() {
var arr = [10]int{4,5,7,11,8,9}
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
//验证数组是值拷贝传递
AddOne(arr)
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
} func AddOne(arr [10]int){
arr[9] = 999999
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,999999]
}

2.Golang中的切片(slice) 

1.首先看看slice的源码结构:

type slice struct {
array unsafe.Pointer
len int
cap int
}

  slice是一个特殊的引用类型,但是它自身也是个结构体

属性len表示可用元素数量,读写操作不能超过这个限制,不然就会panic

属性cap表示最大扩张容量,当然这个扩张容量也不是无限的扩张,它是受到了底层数组array的长度限制,超出了底层array的长度就会panic

2.slice的创建:

func main() {
var arr = [...]int{0,1,2,3,4,5,6}
slice1 := arr[1:4:5] //{low:high:max} 最多再扩张一个元素
//max超出 len(arr)
//slice2 := arr[1:4:7] //panic
fmt.Println(slice1) //[1,2,3]
slice3 := slice1[1:3:4] //[2,3] 大于4会panic
fmt.Println(slice3)
}

 上面代码中创建了一个长度为7的数组arr,同时创建一个基于数组arr的切片slice1,切片引用了数组的index=1到index=3之间的元素,同时也允许切片最大扩张1个元素大小的空间。如果这个扩张空间大于7那么程序就会panic。最后创建了一个基于slice1延申的一个切片slice2,它引用了切片的index=1到index=3之间的元素,由于slice1最大扩容1个元素,因此slice2也最多扩容一个元素,超过了会panic。

创建基于底层数组的slice,其cap取值在: len<=cap<=len(arr)之间

创建基于一个切片的slice,其cap取值在: len(slice1)<=cap<=cap(slice1)之间

3.slice使用make创建

func main() {
var slice = make([]int,3,5) //len=3,cap=5
fmt.Println(slice) //[0,0,0]
slice2:=slice[:5] //slice实现了对slice的扩容,切片长度变为5
fmt.Println(slice2) //[0,0,0,0,0]
}

4.切片作为参数传递

func main() {
var slice = make([]int,3,5) //len=3,cap=5
fmt.Println(slice) //[0,0,0]
slice2:=slice[:5] //slice实现了对slice的扩容,切片长度变为5
fmt.Println(slice2) //[0,0,0,0,0] slice[0] = 999 //这里slice和slice的index=0位置都是999 因为他们引用的底层数组的index=0位置都是999
fmt.Println(slice)
fmt.Println(slice2) AddOne(slice) //[8888,0,0]
fmt.Println(slice) //[8888,0,0]
fmt.Println(slice2) //[8888,0,0,0]
} func AddOne(s []int){
s[0] = 8888
fmt.Println(s)
}

  因为切片是个引用类型,所以它作为参数传递给函数,函数操作的实质是底层数组

3.Golang中的切片追加append()

func main() {
var arr = [...]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4]
slice := arr[:]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,[]int{5,6,7}...) //此时slice的引用地址已经发生改变了,它引用的底层数组再也不是arr了,而是一个新的数组newarr[1,2,3,4,5,6,7]
fmt.Println(slice) //[1,2,3,4,5,6,7]
//验证slice引用的地址已经发生改变
slice[0] = 666
fmt.Println(arr) //[1,2,3,4]
fmt.Println(slice) //[666,2,3,4,5,6,7]
}

  这里由于slice进行追加的元素超出了原来数组的大小,因此go内部会帮我们创建一个新的底层数组,而slice的引用地址不再是arr了,变成了新创建的数组。

还有一种情况就是当slice进行追加的时候没有超出原来数组的大小的时候,其引用地址没有发生改变

func main() {
var arr = [6]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4,0,0]
slice := arr[:4]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,5)
fmt.Println(arr) //[1,2,3,4,5,0]
fmt.Println(slice) //[1,2,3,4,5]
}

4.总结

    (1)go是有数组的,只是平时用切片比较多。数组大小一旦创建就不能改变,数组长度大于元素个数的时候会用0补位,这跟其他语言是相通的。

(2)切片slice可以看作是对数组的一切操作,它是一个引用数据类型,其数据结构包括底层数组的地址,以及元素可操作长度len或可扩容长度cap。

(3)要想突破slice的扩容cap限制进行无限扩容就需要使用append()函数进行操作。如果append追加的元素后slice的总长度不超过底层数组的总长度,那么slice引用的地址不会发生改变,反之引用地址会           变成新的数组的地址。

(4)slice是一个抽象的概念,它存在的意义在于方便对一个顺序结构进行一些方便操作,例如查找,排序,追加等等,这个类似于python的list。

Golang中的Slice与数组的更多相关文章

  1. golang中,slice的几个易混淆点

    slice在golang中是最常用的类型,一般可以把它作为数组使用,但是比数组要高效呀.不过,我感觉这个东西用的不好坑太多了.还是需要了解下他底层的实现 slice的结构定义 type slice s ...

  2. golang中的slice翻转存在以及map中的key判断

    //slice翻转 func stringReverse(src []string){ if src == nil { panic(fmt.Errorf("the src can't be ...

  3. golang中不定参数与数组切片的区别

    package main import "fmt" func main() { myfunc1(, , , ) //传递不定数量的参数 myfunc2([], , , }) //传 ...

  4. 说说不知道的Golang中参数传递

    本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为.在golang中存在着m ...

  5. golang中Array与Slice

    在golang中有数组和Slice两种数据结构,Slice是基于数组的实现,是长度动态不固定的数据结构,本质上是一个对数组字序列的引用,提供了对数组的轻量级访问.那么在go的函数中以数组或Slice为 ...

  6. golang中判断两个slice是否相等

    在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了. slice相等的定义 我们选 ...

  7. [Golang]-1 Slice与数组的区别

    目录 数组 1.创建数组: 2.数组是值拷贝传递: 切片(slice) 1.首先看看slice的源码结构: 2.slice的创建: 3.slice使用make创建 4.切片作为参数传递 5.Golan ...

  8. golang中数组指针与指针数组的区别实现

      指针数组和数组的指针,指的是两个不同的东西. 指针数组是有指针组成的数组,数组的指针是一个数组的指针. package main import "fmt" const MAX ...

  9. Golang 入门 : 切片(slice)

    切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...

随机推荐

  1. 高通量计算框架HTCondor(四)——案例准备

    目录 1. 正文 1.1. 任务划分 1.2. 任务程序 2. 相关 1. 正文 1.1. 任务划分 使用高通量计算第一步就是要针对密集运算任务做任务划分.将一个海量的.耗时的.耗资源的任务划分成合适 ...

  2. 7、python基本数据类型之散列类型

    前言:python的基本数据类型可以分为三类:数值类型.序列类型.散列类型,本文主要介绍散列类型. 一.散列类型 内部元素无序,不能通过下标取值 1)字典(dict):用 {} 花括号表示,每一个元素 ...

  3. 《唐三学node.js系列》—魂士篇&&三哥初始node.js

    前言 如果你有一定的前端基础,比如 HTML.CSS.JavaScript.jQuery.那么Node.js 能让你以最低的成本快速过渡成为一个全栈工程师(我称这个全栈为伪全栈,我认为的全栈也要精通数 ...

  4. 趣学CCNA 路由与交换

    第1章 OSI和TCP/IP 11.1 协议与协议分层 31.2 OSI参考模型 61.2.1 物理层 91.2.2 数据链路层 91.2.3 网络层 101.2.4 传输层 101.2.5 会话层 ...

  5. 发现 一个业务管理系统 解决了 orm 和 前端框架 剩下的 是 业务逻辑 了 。 哈

    解决了 orm 和 前端框架 剩下的 是 业务逻辑 了 . 哈 还有 各种 aop 组件 呢 . 大家 high 来 准备 用 fluent data  和 mysql 写一个 wcf 的 接口呢. ...

  6. .net core之编辑json配置文件

    .net core之编辑json配置文件 引言 最近在具体项目开发应用中,项目采用的json格式配置文件,配置文件的加载采用的IConfiguration接口对象进行的管理,这是.net standa ...

  7. Python - Unittest小结

    一.Unittest 单元测试框架,可用于自动化测试用力组织,执行,输出结果 二.Unittest构成 Test Case Test Suite Test Fixture Test Runner (图 ...

  8. 使用自定义注解和springAOP捕获Service层异常,并处理自定义异常

    一 自定义异常 /** * 自定义参数为null异常 */ public class NoParamsException extends Exception { //用详细信息指定一个异常 publi ...

  9. DWZ框架-- Dialog点击保存后不能自动关闭

    案例 今天在用DWZ框架做添加功能时,发现在对话框保存成功后,后端返回正确的json格式,但对话框不能自动关闭窗口,而且保存后自动跳回主页,没有停留在当前用户列表页面,具体错误过程重现如下: 1.打开 ...

  10. ROS中3D机器人建模(一)

    一,机器人建模的ROS软件包 *urdf : 机器人建模最重要的ros软件包是urdf软件包.这个软件包包含一个用于统一机器人描述格式(URDF)的C++解析器,它是一个表示机器人模型的XML文件,还 ...