GoLang:数组、切片
学习自:GoLang学习手册89页
2)操作数组的几种方式
①数组名:arr[i]
②指针:(*p)[i]
③指针:p[i]
1 2 3 4 5 6 7 8 9 10 11 | //①数组名:arr[i] //②指针:(*p)[i] //③指针:p[i] var p *[3]int var arr [3]int=[3]int{1,2,3} p=&arr <br> //三种方法 arr[2] (*p)[2] p[2] |
1、一维数组
1)定义:var 名称 [数量] 类型
-
定义但不初始化:var 名称 [数量] 类型
//只定义不初始化 var arr [3]int //定义时未指定初值,会采用该类型的默认值[0,0,0]
-
定义时初始化:var 名称 [数量] 类型=[数量]类型{值1,值2,...}
//完全初始化 var arr [3]int = [3]int{1,3,5} //部分初始化 var arr [3]int = [3]int{1,3} //[1,3,0]
//部分初始化,指定具体位置上的元素进行初始化 var arr [3]int = [3]int{0:8,2:9}//0号索引赋值8,2号索引赋值9,1号取默认0
//省略类型与长度,...会根据元素个数自动确认数组长度 arr := [...]int{1,3,5}
//省略类型与长度,但需指定最后一个元素的值 arr := [...]int{6:5}//索引为6的元素,赋值5 -
定义后初始化:
var arr [3]int //依次初始化 arr[0]=1 arr[1]=2 arr[2]=3 //一次初始化 arr=[3]int{1,2,3}
2)访问
数组长度:len(arr)
打印整个数组:fmt.Println(arr)
索引访问:arr[i] i从0开始
遍历
arr := [...]int{1,3,5} //正常for循环 for i:=0;i<len(arr);i++{ fmt.Println(i,arr[v]) } //for...range for i,v := range arr{ fmt.Println(i,v) }
3)比较
数组的类型要同时考虑①内部元素类型;②数组长度。因此[3]int和[4]int就不是同一种类型。
数组可以用==和!=进行相等判断:
- 进行相等判断的数组必须具有相同类型——相同的元素类型+长度;
- 不同类型的数组,无法比较——不是指不相等,而是连==比较的操作都无法进行(会报错);
- 只有当内含元素支持==、!=,数组才会支持;
- 比较时,会依次比较内部元素
2、二维数组
arr := [...][列数]类型 { {行1},{行2},... }
arr := [...][3]int{ {1,2,3}, {4,5,6}, } fmt.Println(arr) //[[1,2,3] [4,5,6]]
3、切片
理解:动态数组
本质:结构体
//源码 type slice struct{ array unsafe.Pointer //指向底层数组指针 len int //切片长度——已经存了多少了长度 cap int//切片容量——总共可以保存多少
1)创建
①通过数组创建:sce:=arr[start:end]
说明:
-
提取arr从start开始,共(end-start)个元素;
-
提取arr索引从start到end-1的元素
arr:=[...]int{1,2,3,4,5} sce:=arr[0:2] //[1,2] fmt.Println(sce,len(sce),cap(sce))//[1,2] 2 5
补充:
- start、end可以只写其中一个(不写start默认从开头切,不写end默认切到最后),也可以都不写(默认从开头到结尾)
sce与arr的关系
- sce的地址和arr[start]的地址相同
- len=end-start
- cap=len(arr)-start(少了start之前索引处的元素)
②make创建:make(类型,长度,容量)
说明:内部先创建一个相同的数组,再让切片指向它。如果没容量,默认和长度一样。sce:=make([]int,3,5) fmt.Println(sce,len(sce),cap(sce))//[0,0,0] 3 5 //内部实现原理 arr:=[5]int{0,0,0} sce=arr[0,3]
③Go语法糖:sce := [ ]int{值1,值2,值3}
说明:和创建数组相同,但是不指定长度,此法创建的切片,len==cap
sce:=[]int{1,3,5}
fmt.Println(sce,len(sce),cap(sce))//[1,3,5] 3 3
2)使用
①访问
访问:sce[索引]
注意:
- 索引不能超过len
- 可以修改sce指定索引处的值
②追加、扩容:append
如果希望追加时自动扩容,需要用append方法:
- append在切片末尾(sec[len]处)添加一个元素,返回操作后的sce;
- 如果追加后未超过cap,返回原切片;如果超过了,则返回扩容后的新切片;
- 扩容——每次扩容都使cap×2
③拷贝:copy(目标切片,源切片)
作用:将源切片中的数据拷贝到目标切片中
说明:
- 拷贝后的切片地址和拷贝前的切片相同,二者底层指向相同数组(意味着二者在物理地址上相同,对其中任何一个的修改都会影响另一个);
- 对拷贝后切片的修改,会导致拷贝前切片的变化;
- 拷贝时以小容量为准:如果目标切片的cap比原切片大,那会把原切片全部拷贝过去,如果比原切片小,则只拷贝目标切片容量大小的数据
注意:
- 可以对切片进行切片操作得到新的切片,两个切片底层指向同一个数组,对新切片的修改会影响原切片的值(甚至append之后,会使原切片中指定位置处的值被修正为该新加值):
arr:=[...][1,3,5,7,9] sce1:=arr[0:4] sce2:=sce1[0:3]
- 两个切片不支持==、!=运算,切片只支持和nil进行相等判断:
fmt.Println(sce1==sce2)//编译报错 fmt.Println(sce1!=nil) fmt.Println(sce2==nil)
- 只是声明一个切片,而没有实际用make创建是不能使用的
var sce []int sce[0]=2//编译报错
- 字符串底层是[byte]数组,因此字符串也支持切片:
str:="abcdefg" sce1:=str[3:] sce2:=make([]byte,10) copy(sce2,str) fmt.Println(sce2)//[97 98 99 100...]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性