Map的使用
# 一、集合(Map)
# 1.1 什么是Map
map
是Go
中的内置类型,它将一个值与一个键关联起来.可以使用相应的键检索值.Map
是一种无序的键值对的集合.Map
最重要的一点是通过key
来快速检索数据,key
类似于索引,指向数据的值Map
是一种集合,所以可以像迭代数组和切片那样迭代它.不过,Map
是无序的,无法决定它的返回顺序,这是因为Map
是使用hash
表来实现的,也是引用类型
使用map过程中需要注意的几点:
map
是无序的,每次打印出来的map
都会不一样,它不能通过index
获取,而必须通过key
获取map
的长度是不固定的,也就是和slice
一样,也是一种引用类型- 内置的
len
函数同样适用于map
,返回map
拥有的key
的数量 map
的key
可以是所有可比较的类型,如布尔型、整数型、浮点型、复杂型、字符串型……也可以键.
# 1.2 Map的使用
# 1.2.1 使用make()创建map
可以使用内建函数
make
也可以使用map
关键字来定义Map
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable = make(map[key_data_type]value_data_type)
1
2
3
4
5
2
3
4
5
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
1
如果不初始化map
,那么就会创建一个nil map
.nil map
不能用来存放键值对
package main
import "fmt"
func main() {
var countryCapitalMap map[string]string
/* 创建集合 */
countryCapitalMap = make(map[string]string)
/* map 插入 key-value 对,各个国家对应的首都 */
countryCapitalMap["France"] = "Paris"
countryCapitalMap["Italy"] = "Rome"
countryCapitalMap["Japan"] = "Tokyo"
countryCapitalMap["India"] = "New Delhi"
/* 使用 key 输出 map 值 */
for country := range countryCapitalMap {
fmt.Println("Capital of",country,"is",countryCapitalMap[country])
}
/* 查看元素在集合中是否存在 */
captial, ok := countryCapitalMap["United States"]
/* 如果 ok 是 true, 则存在,否则不存在 */
if(ok){
fmt.Println("Capital of United States is", captial)
}else {
fmt.Println("Capital of United States is not present")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
运行结果:
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Capital of United States is not present
1
2
3
4
5
2
3
4
5
# 1.2.2 delete() 函数
delete(map, key)
函数用于删除集合的元素,参数为map
和其对应的key
.删除函数不返回任何值.
package main
import "fmt"
func main() {
/* 创建 map */
countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
fmt.Println("原始 map")
/* 打印 map */
for country := range countryCapitalMap {
fmt.Println("Capital of",country,"is",countryCapitalMap[country])
}
/* 删除元素 */
delete(countryCapitalMap,"France");
fmt.Println("Entry for France is deleted")
fmt.Println("删除元素后 map")
/* 打印 map */
for country := range countryCapitalMap {
fmt.Println("Capital of",country,"is",countryCapitalMap[country])
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
原始 map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
删除元素后 map
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 1.2.3 ok-idiom
- 可以通过
key
获取map
中对应的value
值.语法为:
map[key]
1
但是当key
如果不存在的时候,会得到该value
值类型的默认值,比如string
类型得到空字符串,int
类型得到0
.但是程序不会报错.
所以可以使用ok-idiom
获取值,可知道key/value
是否存在
value, ok := map[key]
1
示例代码:
package main
import (
"fmt"
)
func main() {
m := make(map[string]int)
m["a"] = 1
x, ok := m["b"]
fmt.Println(x, ok)
x, ok = m["a"]
fmt.Println(x, ok)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
运行结果:
0 false
1 true
1
2
2
# 1.2.4 map的长度
- 使用
len
函数可以确定map
的长度.
len(map) // 可以得到map的长度
1
# 1.2.5.map的综合示例代码
package main
import "fmt"
func main() {
/*
map: 映射,是一种专门用于存储键值对的集合,属于引用类型
存储特点:
A: 存储的是无序的键值对
B: 键不能重复,并且和value值一一对应的
map中的key不能重复,如果重复,那么新的value会覆盖原来的,程序不会报错
语法结构:
1.创建map
var map1 map[key类型]value类型
nil map,不能直接使用
var map2 = make(map[key类型])value类型
var map3 = map[key类型]value类型{key:value,key:value,key:value...}
2.添加/修改
map[key]=value
如果key不存在,就是添加数据
如果key存在,就是修改数据
3.获取
map[key]--->value
value,ok := map[key]
根据key获取对应的value
如果key存在,value就是对应的数据,ok为true
如果key不存在,value就是值类型的默认值,ok为false
4.删除数据
delete(map,key)
如果key存在,就可以直接删除
如果key不存在,删除失败
5.长度
len()
每种数据类型:
int: 0
float: 0.0 ---> 0
string: ""
array: [0000]
slice: nil
map: nil
*/
//1.创建map
var map1 map[int]string // 只有声明,没有初始化,nil
var map2 = make(map[int]string) //创建
var map3 = map[string]int{"GO": 98, "python": 87, "Java": 79, "Html": 93}
fmt.Println(map1)
fmt.Println(map2)
fmt.Println(map3)
fmt.Println(map1 == nil)
fmt.Println(map2 == nil)
fmt.Println(map3 == nil)
//2.nil map
if map1 == nil {
map1 = make(map[int]string) // 使用make创建map的话,map就不为空
fmt.Println(map1 == nil)
}
//3.存储键值对到map中
map1[0] = "hello" // panic: assigment to entry in nil map
map1[1] = "world"
map1[2] = "memeda"
map1[3] = "王二狗"
map1[4] = "ruby"
map1[5] = "三胖思密达"
map1[6] = ""
//4.获取数据,根据key获取对应的value值
//根据key获取对应的value,如果key存在,获取数值,如果key不存在,获取的是value值类型的零值(默认值)
fmt.Println(map1)
fmt.Println(map1[4])
v1, ok := map1[40]
if ok {
fmt.Println("对应的数值是: ", v1)
} else {
fmt.Println("操作的key不存在,获取到的是零值: ", v1)
}
// 5.修改数据
fmt.Println(map1)
map1[2] = "如花" // 如果这个值存在就做修改,如果不存在就新增
fmt.Println(map1)
//6.删除数据
delete(map1, 2)
fmt.Println(map1)
delete(map1, 30)
fmt.Println(map1)
//7.长度
fmt.Println(len(map1)) //6是指存储了6个key
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 1.2.6 map是引用类型的
- 与切片相似,映射是引用类型.当将映射分配给一个新变量时,它们都指向相同的内部数据结构.因此,一个的变化会反映另一个.
package main
import (
"fmt"
)
func main() {
personSalary := map[string]int{
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("Original person salary", personSalary)
newPersonSalary := personSalary
newPersonSalary["mike"] = 18000
fmt.Println("Person salary changed", personSalary)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
运行结果:
Original person salary map[steve:12000 jamie:15000 mike:9000]
Person salary changed map[steve:12000 jamie:15000 mike:18000]
1
2
2
map
不能使用==
操作符进行比较.==
只能用来检查map
是否为空.否则会报错:invalid operation: map1 == map2 (map can only be comparedto nil)
# 1.3.map的遍历
package main
import (
"fmt"
"sort"
)
func main() {
/*
map的遍历:
使用: for range
数组、切片: index,value
map: key,value
*/
map1 := make(map[int]string)
map1[1] = "红孩儿"
map1[2] = "小旋风"
map1[3] = "白骨精"
map1[4] = "白素贞"
map1[5] = "金角大王"
map1[6] = "王二狗"
fmt.Println(map1)
fmt.Println("------------------------")
//1.遍历map
for k, v := range map1 {
fmt.Println(k, v)
}
fmt.Println("------------------------")
for i := 1; i <= len(map1); i++ {
fmt.Println(i, "--->", map1[i])
}
/*
1.获取所有的key,--->切片/数组
2.进行排序
3.遍历key,--->map[key]
*/
keys := make([]int, 0, len(map1))
fmt.Println(keys)
for k, _ := range map1 {
keys = append(keys, k)
}
fmt.Println(keys)
//冒泡排序,或者使用sort包下的排序方法
sort.Ints(keys)
fmt.Println(keys)
for _, key := range keys {
fmt.Println(key, map1[key])
}
s1 := []string{"Apple", "Windows", "Oragne", "abc", "王二狗", "acd", "acc"}
fmt.Println(s1)
sort.Strings(s1)
fmt.Println(s1)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 二、Map结合Slice
# 示例代码
package main
import "fmt"
func main() {
/*
map和slice的结合使用:
1.创建map用于存储人的信息
name,age,sex,address
2.每个map存储一个人的信息
3.将这些map存储到slice中
4.打印遍历输出
*/
//1.创建map存储第一个人的信息
map1 := make(map[string]string)
map1["name"] = "王二狗"
map1["sex"] = "男"
map1["age"] = "30"
map1["address"] = "北京市XXX路XXX号"
fmt.Println(map1)
//2.第二个人
map2 := make(map[string]string)
map2["name"] = "李小花"
map2["age"] = "20"
map2["sex"] = "女性"
map2["address"] = "上海市。。。"
fmt.Println(map2)
//3.第三个人
map3 := map[string]string{"name": "ruby", "age": "30", "sex": "女性", "address": "杭州市"}
fmt.Println(map3)
//将map存入到slice(切片)中
s1 := make([]map[string]string, 0, 3)
s1 = append(s1, map1)
s1 = append(s1, map2)
s1 = append(s1, map3)
fmt.Println(s1)
//遍历切片
for i, val := range s1 {
//val: map1,map2,map3
fmt.Printf("第 %d 个人的信息是: \n", i+1)
fmt.Printf("\t姓名: %s\n", val["name"])
fmt.Printf("\t年龄: %s\n", val["age"])
fmt.Printf("\t性别: %s\n", val["sex"])
fmt.Printf("\t地址: %s\n", val["address"])
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 三、Mpa是引用类型
# 示例代码
package main
import "fmt"
func main() {
/*
一: 数据类型:
基本数据类型: int,float,string,bool
复合数据类型: array,slice,map,function,pointer,struct,...
array: [size]数据类型
slice: []数据类型
map: [key的类型]value的类型
二: 存储特点
值类型: int,float,string,bool,array,struct
引用类型: slice,map
make(),slice,map,chan //make创建出来的都是引用类型数据
*/
map1 := make(map[int]string)
map2 := make(map[string]float64)
fmt.Printf("%T\n", map1)
fmt.Printf("%T\n", map2)
map3 := make(map[string]map[string]string) //map[string]map[string]string
m1 := make(map[string]string)
m1["name"] = "王二狗"
m1["age"] = "30"
m1["salary"] = "3000"
map3["hr"] = m1
m2 := make(map[string]string)
m2["name"] = "ruby"
m2["age"] = "28"
m2["salary"] = "8000"
map3["总经理"] = m2
fmt.Println(map3)
fmt.Println("--------------------------")
map4 := make(map[string]string)
map4["王二狗"] = "矮戳穷"
map4["李小花"] = "白富美"
map4["ruby"] = "住在隔离"
fmt.Println(map4)
map5 := map4
fmt.Println(map5)
map5["王二狗"] = "高富帅"
fmt.Println(map4) //map4发生了变化
fmt.Println(map5) //map5也发生了变化
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
上次更新: 2024/04/09, 16:48:42
- 01
- AWS NAT-NetWork-Firwalld配置(一)04-09
- 02
- AWS NAT-NetWork-Firwalld配置(二)04-09
- 03
- kubernetes部署minio对象存储01-18