【Go】数组,切片,映射

1. Array(数组)

数组定义

1
2
3
4
5
6
//定义一个长度为3,元素类型为int的数组a
var a [3]int
var b [4]string

//数组可以通过下标进行访问,下标从0开始,最后一个元素的下标为 len-1
v := a[len - 1]

数组初始化

1
2
3
4
5
6
7
8
9
10
func main() {
var testArray [3]int //数组会初始化为int类型的零值
var numArray = [3]int{1, 2} //使用指定的初始值完成初始化
var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
var numArray = [...]int{1, 2} // 不确定初始化的长度,可以直接使用...代替
fmt.Println(testArray) //[0 0 0]
fmt.Println(numArray) //[1 2 0]
fmt.Println(cityArray) //[北京 上海 深圳]
fmt.Println(numArray) //[1 2]
}

数组的遍历

1
2
3
4
5
6
7
8
9
10
11
12
func main{
var a = [...]int{1,3,5}
//for循环遍历
for i := 0 ; i < len(a) ; i++{
fmt.Println(a[i])
}

//for range遍历
for i,v := range a{
fmt.Println(i,v)
}
}

数组是值类型

数组是值类型,赋值和传参 会 复制整个数组,因此改变副本的值,不会改变本身的值。

如果想改变副本的值,可以使用指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main{
a := [...]int{1,3,5}
modify1(a[0])
fmt.Println(a) //[1,3,5]
modify2(&a[1])
fmt.Println(a) //[1,100,5]
}

func modify1(x int){
x =100
}
//传入一个指针地址,根据这个地址,把 地址对应的值修改为 100。这样值就会被修改了
func modify2(y *int){
*y = 100
}

2. slice(切片)

切片是一个拥有相同类型元素的 可变长度的序列,是对数组的一个封装,支持自动扩容。因为数组不能扩容。
切片是一个引用类型,它的内部结构包含 地址,长度,容量。

切片的定义

1
2
3
4
5
6
7
var name []T

var a []string
var b = []int{}
var c = []bool{false,true}

切面拥有自己的长度和容量,len()函数求长度,cap()函数求容量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

func main{
a := []int{0,1,2,3,4,5}
s := a[1:5] // s := a[low,high]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))

m := a[2:]
n := a[:5]
l := a[:]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", m, len(m), cap(m))
fmt.Printf("s:%v len(s):%v cap(s):%v\n", n, len(n), cap(n))
fmt.Printf("s:%v len(s):%v cap(s):%v\n", l, len(l), cap(l))

/**
s:[1 2 3 4] len(s):4 cap(s):5
s:[2 3 4 5] len(s):4 cap(s):4
s:[0 1 2 3 4] len(s):5 cap(s):6
s:[0 1 2 3 4 5] len(s):6 cap(s):6
*/

}

对于数组或者字符串,必须要考虑数组越界的情况,high的值最大不能超过cap()

使用make()函数来构造切片

1
2
3
4
5
6
7
8
9
10
11
12
13
make([]T, size, cap)
T: 切片的元素类型
size:切片中元素的数量
cap:切片的容量



func main() {
a := make([]int, 2, 10)
fmt.Println(a) //[0 0]
fmt.Println(len(a)) //2
fmt.Println(cap(a)) //10
}

注意的点

  • 切面不能直接用来比较
  • 判断切片是否为空 用len(s) == 0

切片是赋值拷贝

1
2
3
4
5
6
7
func main() {
s1 := make([]int, 3) //[0 0 0]
s2 := s1 //将s1直接赋值给s2,s1和s2共用一个底层数组
s2[0] = 100
fmt.Println(s1) //[100 0 0]
fmt.Println(s2) //[100 0 0]
}

切片的遍历

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
s := []int{1, 3, 5}

for i := 0; i < len(s); i++ {
fmt.Println(i, s[i])
}

for index, value := range s {
fmt.Println(index, value)
}
}

切片添加元素

1
2
3
4
5
6
7
8
9
10
11
func main(){
var s []int
s = append(s, 1) // [1]
s = append(s, 2, 3, 4) // [1 2 3 4]
s2 := []int{5, 6, 7}
s = append(s, s2...) // [1 2 3 4 5 6 7]
}

//添加元素 有可能会触发切片的扩容机制
//如果说当前切片的len和cap相等,此时继续添加元素,就会扩容,大小为原来的2倍

切片的复制

copy()是将一个切片的数据复制到另外一个切片空间中,只复制的是数据。

1
2
3
4
5
6
7
8
9
10
11
func main() {
// copy()复制切片
a := []int{1, 2, 3, 4, 5}
c := make([]int, 5, 5)
copy(c, a) //使用copy()函数将切片a中的元素复制到切片c
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
c[0] = 1000
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1000 2 3 4 5]
}

切片删除元素

要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...)

1
2
3
4
5
6
7
func main() {
// 从切片中删除元素
a := []int{30, 31, 32, 33, 34, 35, 36, 37}
// 要删除索引为2的元素
a = append(a[:2], a[3:]...)
fmt.Println(a) //[30 31 33 34 35 36 37]
}

3. map

map定义

1
map [keyType]ValueType

map类型的变量默认初始值为nil,需要使用make()函数来分配内存。语法为:

1
make(map[KeyType]ValueType, [cap])
1
2
3
4
5
6
7
8
func main() {
scoreMap := make(map[string]int, 8)
scoreMap["张三"] = 90
scoreMap["小明"] = 100
fmt.Println(scoreMap)
fmt.Println(scoreMap["小明"])
fmt.Printf("type of a:%T\n", scoreMap)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func main() {
user := map[string]string{
"name": "mutong",
"age" : "18",
}
fmt.Println(user)

//判断某一个健是否存在
v ,ok := user["name1"]
if ok {
fmt.Println(v)
}else {
fmt.Println("不存在")
}

//map遍历
for i , v := range user{
fmt.Println(i,v)
}
}
使用搜索:谷歌必应百度