4.7 map
map是key-value数据结构,又称为字段或者给关联数组,类似其他编程语言的集合。(映射)
基本语法:var map变量名 map[keytype]valuetype
keytype可以是bool,int,string,指针,channel,还可以是只包含前面几个类型的接口,结构体,数组。通常key为int,string。注意:slice,map还有function不可以,因为没办法用==来判断。
valuetype的类型和key基本一样。
1)map在使用前一定要通过make创造空间make(map[key]value,size)
2)map的key是不能重复,如果重复以最后一个key-value为准,其中的value可以是重复的
3)key-value是无序的,不按照输入顺序,也不按照key值大小排列。
map的使用方式:
1)先声明再make。2)直接map+make。3)直接map+make+赋值keyvalue
//map的声明,声明不分配空间,key不能够重复,value可以重复
var map_1 map[string]string
//在使用map前,需要先make,make的作用就是给map分配数据空间
map_1 = make(map[string]string, 10)
//golang中的map是无序的,不按照key值排序
map_1["num1"] = "jack"
map_1["num2"] = "mary"
map_1["num3"] = "tom"
fmt.Println(map_1)
//方式二,size可以省略
map_2 := make(map[int]string)
map_2[1] = "tom1"
fmt.Println(map_2)
//方式三
map_3 := map[int]string{1: "tom", 2: "jack"}
fmt.Println(map_3)
//map的使用:存放学生信息每个学生学号name和sex信息
stu_map := make(map[int]map[string]string)
//stu1
stu_map[1] = make(map[string]string) //因为内部还有个map,因此还需要一个make
stu_map[1]["name"] = "tom"
stu_map[1]["sex"] = "男"
stu_map[1]["add"] = "北京"
//stu2
stu_map[2] = make(map[string]string)
stu_map[2]["name"] = "jack"
stu_map[2]["sex"] = "男"
stu_map[2]["add"] = "南京"
fmt.Println(stu_map)
map的增删改查及遍历:
//增加就是直接赋值,更新也是直接赋值
map_4 := make(map[int]string)
map_4[1] = "北京"
map_4[2] = "南京"
map_4[3] = "天津"
map_4[4] = "上海"
//删除使用内置函数delete(map名+key)
//如果要删除map中所有的key
//1.遍历逐一删除
//2.可以重新通过make创建一个新空间,将原来直接回收 map_4:=make(...)
delete(map_4, 2)
//查找val表示查询到的值,key表示是否存在,不存在则只输出false
val_1, ok_1 := map_4[1]
val_2, ok_2 := map_4[5]
fmt.Println(val_1, ok_1, val_2, ok_2) //北京 true false
//map的遍历使用for-range的结构遍历,基本不用for循环
for k, v := range map_4 {
fmt.Println(k, v)
}
//遍历多重map
for stu_id, stu := range stu_map {
fmt.Println(stu_id)
for stu_inf, stu_res := range stu {
fmt.Println(stu_inf, stu_res)
}
}
/*1
name tom
sex 男
add 北京
2
name jack
sex 男
add 南京
*/
//返回长度
fmt.Println(len(stu_map)) //输出为2
map切片:
切片的数据类型如果是map,则称为slice of map,map切片,这样map个数就可以动态变化了。实例:动态添加学生信息
func map_slice() {
//注意以下的两个make不相同
var stu []map[string]string
stu = make([]map[string]string, 2) //准备放入两个,创建切片
if stu[0] == nil {
stu[0] = make(map[string]string, 2) //创建映射
stu[0]["name"] = "tom"
stu[0]["age"] = "20"
}
if stu[1] == nil {
stu[1] = make(map[string]string, 2)
stu[1]["name"] = "jack"
stu[1]["age"] = "22"
}
newstu := map[string]string{"name": "小米", "age": "20"}
stu = append(stu, newstu)
fmt.Println(stu)
}
map排序:
func map_sort() {
map1 := make(map[int]string)
map1[10] = "a"
map1[2] = "b"
map1[1] = "c"
map1[3] = "d"
//当前版本已经自动排序
fmt.Println(map1)
//如果未排序,按照key的key顺序进行排序输出
//1. 先将map的key放入到切片中
//2. 对切片进行排序
//3. 遍历切片,然后按照key来输出map的值
var key []int
for k, _ := range map1 {
key = append(key, k)
}
//排序
sort.Ints(key)
fmt.Println(key)
for _, k := range key {
fmt.Printf("map[%v]=%v ", k, map1[k])
}
}
map使用细节:
1)map是引用类型,遵守引用类型传递机制,在一个函数接受map,修改后,会直接修改原来的map
2)map容量达到后,再向map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对(key-value)
3)map的value也经常使用struct类型,更适合管理复杂的数据(比前面value是一个map更好)
##map练习:
编写一个函数modifyUser(users map[string]map[string]string,name string)完成上述功能【如果某个用户名存在,就将其密码修改为”88888“,如果不存在就增加用户信息,包括nickname和pwd】
func modifyUser(users map[string]map[string]string, name string) {
//判断users中是否有name
//v , ok := users[name]
if users[name] != nil {
//有这个用户
users[name]["pwd"] = "888888"
} else {
//没有这个用户
users[name] = make(map[string]string, 2)
users[name]["pwd"] = "888888"
users[name]["nickname"] = "昵称~" + name //示意
}
/*
users := make(map[string]map[string]string, 10)
users["smith"]= make(map[string]string, 2)
users["smith"]["pwd"]="999999"
users["smith"]["nickname"]="小花猫"
modifyUser(users, "tom")
modifyUser(users, "mary")
modifyUser(users, "smith")
fmt.Println(users)
*/
}