持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情
一、map入门
1.1 map简介
map是key-value数据结构,又称为字段或者关联数组。类似其它编程语言的集合
1.2 map语法
var map变量名 map[keytype]valuetype
1.2.1 key类型
**key的类型:例如--> bool,数字,string,指针,channel,还可以是 接口,结构体,数组,通常为 int,string
slice,map,function不可以作为key类型,因为无法使用==判断
1.2.2 value类型
value类型基本和key类型一样,通常为 数字,string,map,struct
1.3 map声明例子
声明不分配内存,初始化需要make,分配内存后才可以赋值、使用
var intMap map[string]string
var intMap map[string]int
var intMap map[int]string
var intMap map[int]map[string]int
1.3.1 案例
package main
import "fmt"
func main() {
// map声明
var strMap map[string]string
// map[]
fmt.Println(strMap)
// 先make,再使用
// make(map[keyType]valueType, 空间大小)
strMap = make(map[string]string, 10)
strMap["name"] = "Amlk"
strMap["name_2"] = "Rus"
strMap["name_2"] = "Rsd"
strMap["name_3"] = "Creddl"
// key无法重复,若重复则是覆盖
// value可以重复
// map[name:Amlk name_2:Rsd name_3:Creddl]
// map是无序的
fmt.Println(strMap)
}
1.4 map注意事项
- map在使用前一定要make
- map的key不能重复,若重复,就是覆盖
- map的value可重复
- map的key-value 是无序的
- make初始化的长度可以省略,省略则为0
二、map的使用方式
2.1 声明再make
var intMap map[int]string
// make
intMap = make(map[int]string, 10)
2.1.1 案例
package main
import "fmt"
func main() {
// 声明方式一
var intMap map[int]string
// make
intMap = make(map[int]string, 10)
intMap[1] = "one"
intMap[2] = "two"
// map[1:one 2:two]
fmt.Println(intMap)
}
2.2 声明同时直接make
vat intMap = make(map[int]string)
2.2.1 案例
package main
import "fmt"
func main() {
// 声明方式二
var intMap = make(map[int]string, 10)
intMap[1] = "one"
intMap[2] = "two"
// map[1:one 2:two]
fmt.Println(intMap)
}
2.3 声明直接赋值
var intMap map[int]string = map[int]string {
1:"one",
.......
}
// 或者
strMap := map[string]int{
"two":2,
......
}
2.3.1 案例
package main
import "fmt"
func main() {
// 声明方式三
var intMap map[int]string = map[int]string{
1: "one",
2: "two",
3: "three",
}
// map[1:one 2:two 3:three]
fmt.Println(intMap)
// 或者
strMap := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
// map[one:1 three:3 two:2]
fmt.Println(strMap)
}
三、map案例
3.1 使用map存放学生信息
使用map的key-value来存放三位学生的信息,每个学生有name和gender信息
package main
import "fmt"
func main() {
// map存储学生信息
// 循环实现**********************************
stuMap := make(map[int]map[string]string, 3)
for i := 0; i < 3; i++ {
name := ""
gender := ""
fmt.Printf("请输入第%v名同学姓名:", i+1)
fmt.Scanln(&name)
fmt.Printf("请输入第%v名同学性别:", i+1)
fmt.Scanln(&gender)
stuMap[i+1] = make(map[string]string)
stuMap[i+1]["name"] = name
stuMap[i+1]["gender"] = gender
}
//请输入第1名同学姓名:wangwang
// 请输入第1名同学性别:male
// 请输入第2名同学姓名:Aliy
// 请输入第2名同学性别:female
// 请输入第3名同学姓名:Mike
// 请输入第3名同学性别:male
// map[1:map[gender:male name:wangwang] 2:map[gender:female name:Aliy] 3:map[gender:male name:Mike]]
fmt.Println(stuMap)
//直接赋值实现****************
stu1Map := map[int]map[string]string{
1: {"name": "WangWangDui", "gender": "male"},
2: {"name": "Aliy", "gender": "female"},
3: {"name": "Mike", "gender": "male"},
}
// map[1:map[gender:male name:WangWangDui] 2:map[gender:female name:Aliy] 3:map[gender:male name:Mike]]
fmt.Println(stu1Map)
}
四、map的增删改查
4.1 map增加和修改
package main
import "fmt"
func main() {
// 增加和更新
strMap := make(map[string]string)
// 增加
strMap["one"] = "111"
strMap["two"] = "222"
strMap["three"] = "333"
// 修改,因为key不能重复,那么重新赋值就是更新
strMap["three"] = "Three"
// map[one:111 three:Three two:222]
fmt.Println(strMap)
}
4.2 map删除
4.2.1 语法
delete(map,"key' ),delete是一个内置函数,如果key存在, 就删除该key-value,如果key不存在,不操作,但是也不会报错
delete(mapName, "KEY")
注意事项
- map无法一次性删除所有的key,只能循环遍历,逐个删除
- 或者 map = make(...),make一个新的,让原来的成为垃圾,被gc回收
4.2.1 案例
package main
import "fmt"
func main() {
// 增加和更新
strMap := make(map[string]string)
// 增加
strMap["one"] = "111"
strMap["two"] = "222"
strMap["three"] = "333"
// 修改,因为key不能重复,那么重新赋值就是更新
strMap["three"] = "Three"
// map[one:111 three:Three two:222]
fmt.Println(strMap)
// 删除
delete(strMap, "two")
// map[one:111 three:Three]
fmt.Println(strMap)
// 删除不存在的键是否报错
delete(strMap, "1111")
// map[one:111 three:Three]
fmt.Println(strMap)
// make清空
strMap = make(map[string]string)
// map[]
fmt.Println(strMap)
}
4.3 查询
package main
import "fmt"
func main() {
findMap := make(map[string]string)
findMap["One"] = "1111"
findMap["Two"] = "2222"
findMap["Three"] = "3333"
value, result := findMap["One"]
if result {
// 存在,值 = 1111
fmt.Printf("存在,值 = %v\n", value)
} else {
fmt.Printf("%v不存在\n", findMap["One"])
}
}
五、map的长度及遍历
map遍历使用for-range结构遍历
5.1 map的长度
map的长度就是map中存在几个key-value对
package main
import "fmt"
func main() {
// map遍历
strMap := make(map[string]string)
strMap["one"] = "1111"
strMap["two"] = "2222"
strMap["three"] = "3333"
// 查看
fmt.Println(strMap)
// 查看长度
// strMap的长度 = 3
fmt.Printf("strMap的长度 = %v\n", len(strMap))
5.2 单层map循环
package main
import "fmt"
func main() {
// map遍历
strMap := make(map[string]string)
strMap["one"] = "1111"
strMap["two"] = "2222"
strMap["three"] = "3333"
// 查看
fmt.Println(strMap)
// for-range
for k, v := range strMap {
//key = one, value = 1111
// key = two, value = 2222
// key = three, value = 3333
fmt.Printf("key = %v, value = %v\n", k, v)
}
}
5.3 多层map循环
package main
import "fmt"
func main() {
strMap1 := make(map[string]map[string]string)
strMap1["One"] = make(map[string]string, 3)
strMap1["One"]["one"] = "1"
strMap1["One"]["two"] = "2"
strMap1["One"]["three"] = "3"
strMap1["Two"] = make(map[string]string, 3)
strMap1["Two"]["one"] = "1"
strMap1["Two"]["two"] = "2"
strMap1["Two"]["Three"] = "3"
strMap1["Three"] = make(map[string]string, 3)
strMap1["Three"]["one"] = "1"
strMap1["Three"]["two"] = "2"
strMap1["Three"]["three"] = "3"
for k1, v1 := range strMap1 {
fmt.Printf("外层key = %v, value = %v\n", k1, v1)
for k2, v2 := range v1 {
fmt.Printf("\t内层key = %v, value = %v\n", k2, v2)
}
// 外层key = Three, value = map[one:1 three:3 two:2]
// 内层key = one, value = 1
// 内层key = two, value = 2
// 内层key = three, value = 3
// 外层key = One, value = map[one:1 three:3 two:2]
// 内层key = one, value = 1
// 内层key = two, value = 2
// 内层key = three, value = 3
// 外层key = Two, value = map[Three:3 one:1 two:2]
// 内层key = Three, value = 3
// 内层key = one, value = 1
// 内层key = two, value = 2
}
}
六、map切片
切片的数据类型如果是map,则我们称为slice of map, map切片,这样使用则map个数就可以动态变化了。
6.1 案例演示
要求:使用一个map来记录monster的信息name和age,也就是说一个monster对应一个map,并且妖怪的个数可以动态的增加=>map切片
package main
import "fmt"
func main() {
// map切片使用
// 声明一个map切片,make长度为2
monsters := make([]map[string]string, 2)
// 增加第一个元素
if monsters[0] == nil {
monsters[0] = make(map[string]string, 2)
monsters[0]["name"] = "牛牛"
monsters[0]["age"] = "1999"
}
if monsters[1] == nil {
monsters[1] = make(map[string]string, 2)
monsters[1]["name"] = "牛马"
monsters[1]["age"] = "100"
}
// 新增
newMonster := map[string]string{
"name": "猪道",
"age": "40",
}
// 使用append添加元素到monster中
monsters = append(monsters, newMonster)
// [map[age:1999 name:牛牛] map[age:100 name:牛马] map[age:40 name:猪道]]
fmt.Println(monsters)
}
七、map排序
- golang中没有-一个专门的方法针对map的key进行排序
- golang中的map默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样,请看本章[案例演示]
- golang中map的排序,是先将key进行排序,然后根据key值遍历输出即可
7.1 案例演示
package main
import (
"fmt"
"sort"
)
func main() {
// map排序案例
intMap := make(map[int]int, 10)
intMap[0] = 10010
intMap[9] = 1330
intMap[5] = 2220
intMap[8] = 8100
// map[0:10010 2:2220 3:1330 8:8100]
fmt.Println(intMap)
// 按照key的顺序排序
keys := []int{}
for k, _ := range intMap {
keys = append(keys, k)
}
// 调用sort.Intskeys()方法
sort.Ints(keys)
fmt.Printf("排序后= %v\n", keys)
// 用key取map中的值
// index,value 会取出。这里只取keys中的value,也就是刚刚添加进群的key
for _, k := range keys {
// map[0] = 10010
// map[5] = 2220
// map[8] = 8100
// map[9] = 1330
fmt.Printf("map[%v] = %v\n", k, intMap[k])
}
}
八、map使用细节
- map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map。详见
8.1 案例一 - map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对(key-value) 详见
8.2 案例二 - map的value也经常使用struct类型,更适合管理复杂的数据(比前面value是-一个map更好),比如value为Student结构体。详见
8.3 案例三
8.1 案例一
package main
import "fmt"
func modify(intMap map[int]int) {
intMap[1] = 1111
}
func main() {
// map引用类型
intMap := map[int]int{
1: 1001,
2: 1002,
3: 1003,
}
modify(intMap)
// after modify() = map[1:1111 2:1002 3:1003]
fmt.Printf("after modify() = %v\n", intMap)
}
8.2 案例二
package main
import "fmt"
func main() {
// 定义map
// make长度为2
intMap := make(map[int]int, 2)
// 添加4个数据
intMap[0] = 1000
intMap[1] = 1000
intMap[2] = 1000
intMap[5] = 1000
// intMap = map[0:1000 1:1000 2:1000 5:1000]
fmt.Println("intMap = ", intMap)
}
8.3 案例三
package main
import "fmt"
// 定义一个Stu结构体
type Stu struct {
Name string
Age int
Native string
}
func main() {
// 结构体案例
/*
1. map的key为学生的学好,全局唯一
2. map的value为学生的结构体,包含学生的名字,籍贯
*/
// 声明map
students := make(map[string]Stu, 5)
// 或者不写结构体中key ===》 stu1 := Stu{"Aliy",20,"USA"}
stu1 := Stu{Name: "Aliy", Age: 20, Native: "USA"}
stu2 := Stu{Name: "Bob", Age: 21, Native: "UK"}
stu3 := Stu{Name: "Crely", Age: 18, Native: "France"}
students["stu1"] = stu1
students["stu2"] = stu2
students["stu3"] = stu3
// 学生信息 = map[stu1:{Aliy 20 USA} stu2:{Bob 21 UK} stu3:{Crely 18 France}]
fmt.Printf("学生信息 = %v\n", students)
fmt.Println()
// 遍历学生信息
for k, v := range students {
fmt.Printf("学生编号%v的信息是:\n", k)
fmt.Printf("\t姓名 = %v, 年龄 = %v, 籍贯 = %v\n", v.Name, v.Age, v.Native)
//
// 学生编号stu1的信息是:
// 姓名 = Aliy, 年龄 = 20, 籍贯 = USA
// 学生编号stu2的信息是:
// 姓名 = Bob, 年龄 = 21, 籍贯 = UK
// 学生编号stu3的信息是:
// 姓名 = Crely, 年龄 = 18, 籍贯 = France
}
}
九、map案例实践
- 使用map[string]map[string]sting 的map类型
- key:表示用户名,是唯一- -的,不可以重复
- 如果某个用户名存在,就将其密码修改"888888", 如果不存在就增加这个用户信息,(包括昵称nickname和密码pwd) 4 .编写一个函数modifyUser(users map[string]map[string]sting, name string) 完成上述功能
package main
import "fmt"
// 定义modifyUser函数
func modifyUser(users map[string]map[string]string, name string) {
if users[name] != nil {
users[name]["pwd"] = "88888888"
} else {
users[name] = make(map[string]string)
users[name]["pwd"] = "88888888"
users[name]["nickname"] = "nickname---" + name
}
}
func main() {
// 声明map
infoMap := make(map[string]map[string]string)
infoMap["Aliy"] = make(map[string]string)
infoMap["Aliy"]["nickname"] = "nickname---Aliy"
infoMap["Aliy"]["pwd"] = "123456789"
infoMap["Bob"] = make(map[string]string)
infoMap["Bob"]["nickname"] = "nickname---bob"
infoMap["Bob"]["pwd"] = "456123465123"
modifyUser(infoMap, "Aliy")
modifyUser(infoMap, "aliy")
for k, v := range infoMap {
fmt.Printf("%v的信息是: \n", k)
for k1, v1 := range v {
fmt.Printf("\t %v = %v\n", k1, v1)
}
}
// Aliy的信息是:
// pwd = 88888888
// nickname = nickname---Aliy
// Bob的信息是:
// nickname = nickname---bob
// pwd = 456123465123
// aliy的信息是:
// pwd = 88888888
// nickname = nickname---aliy
}