Golang中的Slice与数组
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与数组的更多相关文章
- golang中,slice的几个易混淆点
slice在golang中是最常用的类型,一般可以把它作为数组使用,但是比数组要高效呀.不过,我感觉这个东西用的不好坑太多了.还是需要了解下他底层的实现 slice的结构定义 type slice s ...
- golang中的slice翻转存在以及map中的key判断
//slice翻转 func stringReverse(src []string){ if src == nil { panic(fmt.Errorf("the src can't be ...
- golang中不定参数与数组切片的区别
package main import "fmt" func main() { myfunc1(, , , ) //传递不定数量的参数 myfunc2([], , , }) //传 ...
- 说说不知道的Golang中参数传递
本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为.在golang中存在着m ...
- golang中Array与Slice
在golang中有数组和Slice两种数据结构,Slice是基于数组的实现,是长度动态不固定的数据结构,本质上是一个对数组字序列的引用,提供了对数组的轻量级访问.那么在go的函数中以数组或Slice为 ...
- golang中判断两个slice是否相等
在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了. slice相等的定义 我们选 ...
- [Golang]-1 Slice与数组的区别
目录 数组 1.创建数组: 2.数组是值拷贝传递: 切片(slice) 1.首先看看slice的源码结构: 2.slice的创建: 3.slice使用make创建 4.切片作为参数传递 5.Golan ...
- golang中数组指针与指针数组的区别实现
指针数组和数组的指针,指的是两个不同的东西. 指针数组是有指针组成的数组,数组的指针是一个数组的指针. package main import "fmt" const MAX ...
- Golang 入门 : 切片(slice)
切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...
随机推荐
- 高通量计算框架HTCondor(四)——案例准备
目录 1. 正文 1.1. 任务划分 1.2. 任务程序 2. 相关 1. 正文 1.1. 任务划分 使用高通量计算第一步就是要针对密集运算任务做任务划分.将一个海量的.耗时的.耗资源的任务划分成合适 ...
- 7、python基本数据类型之散列类型
前言:python的基本数据类型可以分为三类:数值类型.序列类型.散列类型,本文主要介绍散列类型. 一.散列类型 内部元素无序,不能通过下标取值 1)字典(dict):用 {} 花括号表示,每一个元素 ...
- 《唐三学node.js系列》—魂士篇&&三哥初始node.js
前言 如果你有一定的前端基础,比如 HTML.CSS.JavaScript.jQuery.那么Node.js 能让你以最低的成本快速过渡成为一个全栈工程师(我称这个全栈为伪全栈,我认为的全栈也要精通数 ...
- 趣学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 会话层 ...
- 发现 一个业务管理系统 解决了 orm 和 前端框架 剩下的 是 业务逻辑 了 。 哈
解决了 orm 和 前端框架 剩下的 是 业务逻辑 了 . 哈 还有 各种 aop 组件 呢 . 大家 high 来 准备 用 fluent data 和 mysql 写一个 wcf 的 接口呢. ...
- .net core之编辑json配置文件
.net core之编辑json配置文件 引言 最近在具体项目开发应用中,项目采用的json格式配置文件,配置文件的加载采用的IConfiguration接口对象进行的管理,这是.net standa ...
- Python - Unittest小结
一.Unittest 单元测试框架,可用于自动化测试用力组织,执行,输出结果 二.Unittest构成 Test Case Test Suite Test Fixture Test Runner (图 ...
- 使用自定义注解和springAOP捕获Service层异常,并处理自定义异常
一 自定义异常 /** * 自定义参数为null异常 */ public class NoParamsException extends Exception { //用详细信息指定一个异常 publi ...
- DWZ框架-- Dialog点击保存后不能自动关闭
案例 今天在用DWZ框架做添加功能时,发现在对话框保存成功后,后端返回正确的json格式,但对话框不能自动关闭窗口,而且保存后自动跳回主页,没有停留在当前用户列表页面,具体错误过程重现如下: 1.打开 ...
- ROS中3D机器人建模(一)
一,机器人建模的ROS软件包 *urdf : 机器人建模最重要的ros软件包是urdf软件包.这个软件包包含一个用于统一机器人描述格式(URDF)的C++解析器,它是一个表示机器人模型的XML文件,还 ...