数组和切片
数组
定义一个长度为5的int类型数组以及初始化有两种办法:
var a [5]int
a[0]=1
var b=[5]int{1,2,3}//注意等号位置
但其实,由于数组长度是固定的,所以应该使用切片,而不是数组。
切片
创建
切片相当于一个可变数组,类似于c++STL中的vector或是python中的List。和c++中的vectoe一样,go中的切片也有当前长度,预分配长度一说。其中len代表当前切片已使用长度,cap代表系统已分配给该切片的长度*(包括已使用的和未使用的)*
创建一个初始长度为5切片的方法:
var a []int=make([]int,5,10)//预分配长度为10,已使用长度为5
var b []int//可以先声明,再创建
b=make([]int,5)//可以不声明预长度为多少,系统会自行分配
fmt.Println(len(a),cap(a))
fmt.Println(len(b),cap(b))
fmt.Println(a[5])//会报错index out of range [5] with length 5。因为即使预长度为10,但实际只使用了5。
/*
输出:
5 10
5 5
*/
添加
go中,用append函数给切片添加元素。例子:
var a []int=make([]int,0)
var b []int=make([]int,2)
b[0],b[1]=5,6
a=append(a,1)//给a添加一个元素
fmt.Println(a)
a=append(a, 2,3,4)//给a添加多个元素
fmt.Println(a)
a=append(a,b...)//给a添加一个切片
fmt.Println(a)
/*
输出:
[1]
[1 2 3 4]
[1 2 3 4 5 6]
*/
其中b…表示将b中的元素迭代输出到append函数中。
复制
类似于python中的List,go也有类似于a[0:3]这种写法*(但是不含负数下标)*。同样的,将切片直接赋值给别的切片时,是将地址复制过去了,并不是真正的值复制。如果要进行值复制,需要使用copy函数。
如果切片a的长度为5。那么a[0:2]代表[a[0],a[1]](即左包含右不包含),a[3:]代表[a[3],a[4],a[5]],a[:3]代表[a[0],a[1],a[2]],a[:]代表a所有元素。例子:
a:=make([]int,5)
b:=a//b复制了a[0]的地址
b[0]=123//a[0]将会被改变
c:=a[3:]//c复制了a[3]的地址
c[0]=456//a[3]将会被改变
fmt.Println(a)
d:=make([]int,len(a))
copy(d,a)//将a复制到切片d中
d[0]=789//这个赋值不会对a有影响
fmt.Println(a)
/*
输出:
[123 0 0 456 0]
[123 0 0 456 0]
*/
map
创建
map由于是动态变化的,需要使用make创建。map[a]b中,a为键的类型,b为值的类型。值可以用切片作为其类型。例子:
a:=make(map[int][]int)//键类型为int,值类型为int类型的切片
a[1]=make([]int,0)
a[1]=append(a[1], 123,456)
a[2]=make([]int,0)
fmt.Println(a)
/*
输出:
map[1:[123 456] 2:[]]
*/
查找
比如在a中查找是否有存在键为1的元素,直接a[1]即可。
a:=make(map[int]int)
a[1]=3
value,ok:=a[1]//返回两个参数,如果第二个参数为true,则第一个为当前key对应的value。否则为0(不是nil)
if ok{
fmt.Println(value)
}else {
fmt.Println("不存在")
}
/*
输出:
3
*/
删除
使用delete函数删除map数组中的某一个key及其对应的value。例子:
a:=make(map[int]int)
a[1]=3
delete(a,1)
value,ok:=a[3]
if ok{
fmt.Println(value)
}else {
fmt.Println("不存在")
}
/*
输出:
不存在
*/