当前位置:网站首页>go 数组与切片
go 数组与切片
2022-07-05 13:00:00 【UPythonFish】
go 数组与切片
数组
数组是同一类型元素的集合,类似于python中的集合类型。但是Go 语言中不允许混合不同类型的元素,例如包含字符串和整数的数组。(当然,如果是 interface{} 类型数组,可以包含任意类型)
数组的声明
一个数组的表示形式为 [n]T
。n
表示数组中元素的数量,T
代表每个元素的类型。元素的数量 n
也是该类型的一部分,在定义式,数组的大小就固定了,并且不能修改
func main() {
// 数组的定义方式
var a [3]int // 只定义不赋值
var a [3]int = [3]int{
4, 5, 6} // [3]int 是该数组的数据类型
a := [3]int{
4} // [3] 3 指数组的大小,数组的长度不能大于数组的大小
a := [30]int{
28:1} // 数组大小为30,在索引为28的位置插入数据1,其余值以值类型的 0 值填充
var a = [...]int{
3, 4, 5} // 虽然使用... 初始化,但是长度也固定了,根据值得多少确定长度
var a =[...]int{
50:99}
fmt.Printf("%T",a) // [51]int
// 使用[...] 只支持这一种写法
}
补充:
数字,字符串,布尔,数组 ----》值类型 (值有自己的0值, 数字是0,字符串:"" 布尔:false 数组:元素类型的零值)
切片和map ---->引用类型 零值是 nil (None:python中所有类型的空值都是None)
数组的修改与循环
func main() {
// 数组的通过索引取值与修改值,但是不能超出索引取值范围
var a [3]int = [3]int{
4, 5, 6}
fmt.Println(a)
a[0] = 99
fmt.Println(a[0]) // 99
// 基于索引的循环
for i:=0;i<len(a);i++{
fmt.Println(a[i])
}
for i:=len(a)-1;i>=0;i--{
fmt.Println(a[i])
}
// 基于迭代的循环 range是一个关键字,可以返回一个值,一个值就是索引,可以返回两个值,两个值就是索引和值
for i:=range a{
fmt.Println(a[i])
}
for i,value:=range a{
fmt.Println(i,value)
}
}
多维数据
多维数据,简单点说就是数据套数据,跟python中的列表类型一样,可以无限嵌套,这里仅以2层为例
var a [3][4]int=[3][4]int{
{
3,3,3,3},{
4,4,4},{
5}}
fmt.Println(a)
// 循环(两层循环)
for _,value:=range a{
for _,v:=range value{
fmt.Println(v)
}
}
切片
切片是由数组建立的一种方便、灵活且功能强大的包装,切片本身不拥有任何数据,它们只是对现有数组的应用(指针指向数组)
切片的定义
1. 定义一个空切片
var s []int // 括号中不带任何东西就是切片内型
2. 基于数组,引用赋值
a:=[10]int{
1,2,3,4,5,6,7,8,9,10}
var s []int
// 把数组从头到尾的引用给s两种写法
s=a[0:len(a)] // 前闭后开区间
s=[:]
fmt.Printf("s的类型是:%T,值是:%v",s,s) // s的类型是:[]int,值是:[1 2 3 4 5 6 7 8 9 10]
3. 定义切片并初始化
var s []int=[]int{
2,3,4}
fmt.Println(s)
fmt.Println(len(s)) // 长度是3
fmt.Println(cap(s)) // 容量是3
切片的使用
使用也就是通过索引取值和改值
a:=[10]int{
1,2,3,4,5,6,7,8,9,10}
var s []int
s=[:]
fmt.Println(s[0]) // 1
s[0]=999
fmt.Println(s[100]) // 编译不会报错,但是执行会,因为超出了切片的长度
fmt.Println(s) // [999 2 3 4 5 6 7 8 9 10]
fmt.Println(a) // [999 2 3 4 5 6 7 8 9 10]
你会发现当切片修改值时,底层数组的值也会发生相应的变化,始终与切片保存一致
结论1: 切片的变化,会影响底层数组跟着变化,同理,底层数组变化也会影响到切片变化
切片的长度和容量
数组有长度,并且长度是不能改变的,切片也有长度,但是长度可以改变,并且切片有容量
a:=[10]int{
1,2,3,4,5,6,7,8,9,10}
var s []int=a[0:3] // 前闭后开区间
fmt.Println(s) // [1,2,3]
// 切片的长度,指当前切片有多长
fmt.Println(len(s)) // 3
// 切片的容量 : 这个切片最多能存多少值,基于底层数组来的
fmt.Println(cap(s)) //cap 内置函数,计算切片的容量 10
但是需要注意的是,切片的容量并不是一定等于底层数组的长度
a:=[10]int{
1,2,3,4,5,6,7,8,9,10}
var s []int=a[3:6] // 前闭后开区间
fmt.Println(s) // [4,5,6]
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 7
相信到这,也能够看出来了,切片容量是底层数组决定的,容量大小取决于切片是从那个地方开始切取数组的,容量 = 数组长度 - 切取起点(索引值)
make函数
可以通过make函数来创建切片,make函数有三个参数
- 第一个是类型 还可以用来创建其他类型数据
- 第二个是切片的长度
- 第三个是切片的容量
var s []int=make([]int,3,4) // 创建并赋值,但是没有放进去值,默认 0 值,
fmt.Println(s) // [0 0 0]
fmt.Println(len(s)) // 长度是3
fmt.Println(cap(s)) // 容量是4
追加切片
切片可以通过append内置函数添加值
var s =make([]int,3,4)
fmt.Println(s) // [0 0 0]
fmt.Println(len(s)) //3
fmt.Println(cap(s)) //4
s=append(s,99)
fmt.Println(s) // [0 0 0 99]
fmt.Println(len(s)) //4
fmt.Println(cap(s)) //4
// 当切片已经到了容量的最大值时,如果再追加,长度+1,容量基于原来的容量翻倍,自动扩容
s=append(s,88)
fmt.Println(s)
fmt.Println(len(s)) // 5
fmt.Println(cap(s)) // 8
那么问题来了,通过前面的学习我们知道,切片是基于底层数组的引用,追加切片后底层数组是如何变化的呢?
a:=[10]int{
1,2,3,4,5,6,7,8,9,10}
s:=a[2:9]
fmt.Println(s)
// 切片变,底层数组会变
s[0]=666
fmt.Println(s) //[666 4 5 6 7 8 9]
fmt.Println(a) //[1 2 666 4 5 6 7 8 9 10]
// 数组变化,切片也会变
a[8]=999
fmt.Println(a) //[1 2 666 4 5 6 7 8 999 10]
fmt.Println(s) //[666 4 5 6 7 8 999]
切片追加到临界状态,再追加,数组就不够了,又会发生什么变化呢(代码接上)?
s=append(s,222)
fmt.Println(s) // [666 4 5 6 7 8 999 222]
//底层数组?也会跟着变
fmt.Println(a) // [1 2 666 4 5 6 7 8 999 222]
可以看到,如果底层数组不够了,切片再追加,不会再影响原数组。
go语言会自动申请一个新的数组,大小为原来切片容量的2倍,并将原来切片的值,复制到新的数组上,此时切片就跟原数组脱离了,指针指向了新数组
s=append(s,333)
fmt.Println(s) //[666 4 5 6 7 8 999 222 333]
fmt.Println(len(s)) //9
fmt.Println(cap(s)) //16
多维切片
数组中有多维数组,切片基于数组,同样也有多维切片
var s [][]int
// 定义并初始化
var s [][]int=[][]int{
{
1,1,1,1,1,1,1,1,1,1,1},{
2,2,},{
3,3,3,3}}
fmt.Println(s)
fmt.Println(len(s)) // 3 内层一个切片算一个值
fmt.Println(cap(s)) // 3
// 通过 make 初始化
var s [][]int=make([][]int,3,4)
// 内层的切片,没有初始化,只要使用内层切片,内层所有的切片都要初始化
fmt.Println(s[0]) // [] 切片,这个切片没有初始化
// fmt.Println(s[0][0]) // 报错
s[0]=make([]int,5,6) // 对内层切片初始化
s[0][0]=99
fmt.Println(s[0])
fmt.Println(s[0][5]) // 切片越界,虽然容量是6,但是还没使用到,就不能取
//循环多维切片(基于索引,基于迭代)
var s [][]int=[][]int{
{
1,1},{
2,2},{
3,3,3,3}}
for i:=0;i<len(s);i++{
for j:=0;j<len(s[i]);j++{
fmt.Println(s[i][j])
}
}
for _,v:=range s{
for _,v1:=range v{
fmt.Println(v1)
}
}
copy 切片
把一个切片,复制到另一个切片上,使用情景如下(内存优化方案)
var a [10000]int=[10000]int{
3,4,5}
fmt.Println(a)
s:=a[:3]
fmt.Println(s)
// 只要使用s,底层基于了一个很大的数组,内存占用就很高
// 时候,就可以把s copy到另一个基于小数组的切片上
s1:=make([]int,3,3)
fmt.Println(s1) // [0 0 0]
copy(s1,s)
fmt.Println(s1) //[3 4 5] ,以后都用s1操作,节约了内存
但是也有个问题,两个切片一样长,可以copy,如果不一样长呢?
s1:=make([]int,5,5)
s2:=make([]int,2,2)
copy(s1,s)
copy(s2,s)
fmt.Println(s1) // [3 4 5 0 0]
fmt.Println(s2) // [3 4]
可以很明显的看出来,容量不够就只copy部分,容量超了就以 零 型数据填充
边栏推荐
- Detailed explanation of navigation component of openharmony application development
- Rocky基础知识1
- How to protect user privacy without password authentication?
- 阿里云SLB负载均衡产品基本概念与购买流程
- From the perspective of technology and risk control, it is analyzed that wechat Alipay restricts the remote collection of personal collection code
- STM32 and motor development (from architecture diagram to documentation)
- Shu tianmeng map × Weiyan technology - Dream map database circle of friends + 1
- RHCSA1
- ASEMI整流桥HD06参数,HD06图片,HD06应用
- 初识Linkerd项目
猜你喜欢
CF:A. The Third Three Number Problem【关于我是位运算垃圾这个事情】
SAE international strategic investment geometry partner
使用 jMeter 对 SAP Spartacus 进行并发性能测试
Lb10s-asemi rectifier bridge lb10s
Shu tianmeng map × Weiyan technology - Dream map database circle of friends + 1
Flutter 绘制波浪移动动画效果,曲线和折线图
Principle and performance analysis of lepton lossless compression
Lepton 无损压缩原理及性能分析
Pandora IOT development board learning (HAL Library) - Experiment 7 window watchdog experiment (learning notes)
量价虽降,商业银行结构性存款为何受上市公司所偏爱?
随机推荐
CF:A. The Third Three Number Problem【关于我是位运算垃圾这个事情】
程序员成长第八篇:做好测试工作
国际自动机工程师学会(SAE International)战略投资几何伙伴
CAN和CAN FD
Why is your next computer a computer? Explore different remote operations
Association modeling method in SAP segw transaction code
Asemi rectifier bridge hd06 parameters, hd06 pictures, hd06 applications
946. 验证栈序列
Yyds dry goods inventory # solve the real problem of famous enterprises: move the round table
Flutter 绘制波浪移动动画效果,曲线和折线图
How to realize batch sending when fishing
uni-app开发语音识别app,讲究的就是简单快速。
SAP UI5 DynamicPage 控件介紹
PyCharm安装第三方库图解
CloudCompare——点云切片
跨平台(32bit和64bit)的 printf 格式符 %lld 输出64位的解决方式
Reverse Polish notation
【Hot100】34. 在排序数组中查找元素的第一个和最后一个位置
SAP UI5 FlexibleColumnLayout 控件介绍
Lb10s-asemi rectifier bridge lb10s