当前位置:网站首页>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部分,容量超了就以 零 型数据填充
边栏推荐
- SAP SEGW 事物码里的导航属性(Navigation Property) 和 EntitySet 使用方法
- 使用 jMeter 对 SAP Spartacus 进行并发性能测试
- Small case of function transfer parameters
- About the single step debugging of whether SAP ui5 floating footer is displayed or not and the benefits of using SAP ui5
- Reflection and imagination on the notation like tool
- 155. Minimum stack
- Datapipeline was selected into the 2022 digital intelligence atlas and database development report of China Academy of communications and communications
- AVC1与H264的区别
- Simple page request and parsing cases
- 解决uni-app配置页面、tabBar无效问题
猜你喜欢

蜀天梦图×微言科技丨达梦图数据库朋友圈+1

CAN和CAN FD

SAP SEGW 事物码里的 ABAP Editor

量价虽降,商业银行结构性存款为何受上市公司所偏爱?

Introduction to sap ui5 flexiblecolumnlayout control

Talk about my drawing skills in my writing career

无密码身份验证如何保障用户隐私安全?

SAP ui5 objectpagelayout control usage sharing

Datapipeline was selected into the 2022 digital intelligence atlas and database development report of China Academy of communications and communications

Overflow toolbar control in SAP ui5 view
随机推荐
自然语言处理从小白到精通(四):用机器学习做中文邮件内容分类
Pycharm installation third party library diagram
SAP SEGW 事物码里的 ABAP Editor
Write macro with word
Rocky基础命令3
自然语言处理系列(一)入门概述
Run, open circuit
Developers, is cloud native database the future?
MySQL giant pit: update updates should be judged with caution by affecting the number of rows!!!
It's too convenient. You can complete the code release and approval by nailing it!
Simple page request and parsing cases
How to protect user privacy without password authentication?
SAP SEGW 事物码里的 ABAP 类型和 EDM 类型映射的一个具体例子
Asemi rectifier bridge hd06 parameters, hd06 pictures, hd06 applications
DataPipeline双料入选中国信通院2022数智化图谱、数据库发展报告
155. Minimum stack
RHCAS6
The Research Report "2022 RPA supplier strength matrix analysis of China's banking industry" was officially launched
RHCSA3
RHCSA7