Go语言基础之数组 切片 和映射
数组
数组:相同类型的一组数据,一旦定义之后,大小不能发生改变
下面是操作数组的一些栗子
func test( a[5] int) int { //数组作参数时必须规定大小和类型
return a[0]
}
func main() {
//几种声明和初始化数组的方式
var a [5] int //仅声明
a[0],a[1],a[2]=3,4,5
fmt.Println(a,len(a),cap(a))
var b =[5] int {1,2,3} //声明的时候初始化 注意数值个数必须比数组大小要小
fmt.Println(b,len(b),len(b))
var c=[] int {1,2,3,4} //不规定大小的初始化,Go自动根据个数设置大小
fmt.Println(c,len(c),cap(c))
d:=[] float64{5.0,6.0,7.0}
fmt.Println(d,len(d),cap(d))
e:=[...] int{0:2,5:9,9:11} //在特定位置赋值
fmt.Println(e,len(e),cap(e))
//数组是值类型,对赋值的新变量进行修改,不会在原始数组中表现出来
f:=a
f[0]=999
fmt.Println(a,len(a),cap(a))
fmt.Println(f,len(f),cap(f))
//多维数组
var n =[2][2]int {{1,2},{3,4}}
fmt.Println(n,len(n),cap(n))
//多维数组的遍历
for _,v :=range n {
for _,v2:= range v {
fmt.Println(v,v2)
}
}
//数组作为参数
fmt.Println(test(a),test(b))
}
//
输出:
[3 4 5 0 0] 5 5
[1 2 3 0 0] 5 5
[1 2 3 4] 4 4
[5 6 7] 3 3
[2 0 0 0 0 9 0 0 0 11] 10 10
[3 4 5 0 0] 5 5
[999 4 5 0 0] 5 5
[[1 2] [3 4]] 2 2
[1 2] 1
[1 2] 2
[3 4] 3
[3 4] 4
3 1
注意:
-
遍历数组的两种方式分别是for i<len(arraryname)和 for range **
-
数组是值类型
-
数组作为形参要规定长度
-
数组支持逻辑运算符== !=等,其中==成立的数组,每个元素的值都要等
-
[n] * type表示指针数组,* [n] type 表示数组指针
-
对数组使用[:]冒号运算符的时候,其实是通过指针进入到数组里数据的地址,对其进行拷贝或者修改,也就是说修改截取之后新的数组的值,是会改变原数组的值的
切片
切片:Go的切片是对数组的抽象,与数组相比,切片的长度是不固定的。可以追加元素(不仅增加了切片的len也增加了cap),本质是封装好的数组,包含了三个信息:底层数组的指针,切片的长度和切片的容量
关于切片的一些操作
func main() {
var a [] int
b:=make([]int,10) // 10为length
b[0]=2
c:=make([]int,10,20) //10为length ,20为cap]
d:=[] int {2,3,4,5,6,7,8,9,0,1}
/*a[0]=1
a[1]=2
a[2]=3 */ //当声明了切片 却没有给len的时候,再进行赋值是会报错的
//因为我们声明了却没有实例化 那么len和cap都是0 赋值的过程相当于下标溢出
a=append(a,1) //用append塞进去是对的
//: 运算符
fmt.Println(d[:])
e:=d[1:4]//d[1] 到 d[3] 即 3 4 5
fmt.Println(e,len(e),cap(e))
fmt.Println(len(a),cap(a))
fmt.Println(len(b),cap(b))
fmt.Println(len(c),cap(c)) //len是切片中元素的数量 cap是从创建切片的索引开始的底层数组中元素的数量
//更改切片的值 因为切片是引用传递 所有相关的副本都会反映出来
d[1]=20
fmt.Println(d[:])
fmt.Println(e[:])
copy(c,b) //把b的值拷贝到c中
b[0]=1
fmt.Println(b)
fmt.Println(c) //copy之后改变原来的slice的值,是不会对新slice产生影响的
}
检查切片是否为空
var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil 因为已经初始化数组了
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
//应该用len(s)==0 判断,而不是s==nil
比较两个切片
引用类型是不能直接比较的,只能和nil进行比较,值类型是可以直接比较的
删除切片的方法
要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...) //要把一个切片append到另一个切片里 一定要写...
//把一个数或者几个数往slice里面append可以直接写
//把slice往slice里面塞,后缀一定要用...
切片的复制
我们可以用等号直接将一个切片赋值给另一个切片,但是这不是值传递,而是引用传递,即一个切片的值被修改,另一个切片的值也会被修改,原因是因为这两个切片的地址是一致的,想要做到真正的复制只能使用copy函数
映射
映射:Go中的内置类型,它将一个值和一个键关联起来,底层实现是hash,是一种无序的键值对集合,也是引用类型
一些栗子
func main() {
//初始化map
//1.make
map1:=make(map[int]string)
fmt.Println(len(map1)) //0
fmt.Println(map1==nil) //flase make创建引用类型时默认初始化
map1[1]="爱小黄"
map1[0]="爱妈妈"
map1[2]="爱爸爸"
fmt.Println(map1,len(map1)) //len=3,即键值对的个数
v,ok:=map1[0]
fmt.Println(v,ok) //v 是value ,ok 是判断是否存在的bool值
delete(map1,0)//删除map1为0的索引值
fmt.Println(map1)
//2.:map的方式初始化Map
map2:=map[int]string{1:"爱你"}
fmt.Println(map2)
//map是不能拷贝的,我们想拥有一个一模一样的map只能用for range然后赋值的方式
}
注意:
-
map打印的时候是无序输出的,因为底层实现是hash
-
删除Map中的某一个值,使用delete函数
-
Map不能使用copy函数,想要进行Map的复制只能通过for range的方式手动赋值
-
无论是slice array还是map等数据类型,我们在声明的时候都是没有占据内存的,也就是并没有实例化,而如果我们使用Make函数,哪怕cap是0,也是已经分配内存了的
-