map
是一种键值对数据结构,又称为字段或者关联数组,类似于其他编程语言中的集合。
声明
基本语法:
// 方式一:直接声明 + make 初始化
var myMap map[string]int
myMap = make(map[string]int)
// 方式二:直接 make(推荐)
myMap := make(map[string]int)
// 方式三:字面量方式(快速创建)
myMap := map[string]int{
"apple": 5,
"banana": 3,
"orange": 8,
}
注意:
var m map[int]string只是声明了变量,但未分配内存!不能直接赋值,否则会 panic。- 键(key)必须是可比较的类型(如:int, string, bool, struct 等),不能是 slice、map、function。
- key不可以重复,值可以重复,键值对是无序的

使用
嵌套
map可以单个使用,也可以嵌套在一起使用,话不多说我们上案例,比如我现在存储学生的学号,姓名,性别
//存储学生的学号,姓名,性别
students := make(map[string]map[string]string)
students["1001"] = map[string]string{
"name": "威龙",
"sex": "男",
}
students["1002"] = map[string]string{
"name": "麦晓雯",
"sex": "女",
}
students["1003"] = map[string]string{
"name": "乌鲁鲁",
"sex": "男",
}
fmt.Println(students)
fmt.Println(students["1003"]["name"])
}

CRUD 操作(Create, Read, Update, Delete)以及遍历
我们就用最经典最经典的学生信息管理系统来分析
//存储学生的学号,姓名,性别
students := make(map[string]map[string]string)
students["1001"] = map[string]string{
"name": "威龙",
"sex": "男",
}
students["1002"] = map[string]string{
"name": "麦晓雯",
"sex": "女",
}
students["1003"] = map[string]string{
"name": "乌鲁鲁",
"sex": "男",
}
fmt.Println(students)
fmt.Println(students["1003"]["name"])
//CURD操作
//查询
val, exists := students["1001"]
if exists {
fmt.Printf("学号1001的学生是:%s\n", val)
} else {
fmt.Println("未找到该学生")
}
//不安全的查询方式(会返回零值)
fmt.Println("查询不存在的key:", students["999"])
//更新
students["1001"]["name"] = "红狼"
fmt.Println("更新后:", students)
//删除
delete(students, "1002")
fmt.Println("删除后:", students)
// 遍历
fmt.Println("\n最终所有学生:")
for id, info := range students {
fmt.Printf("学号: %s, 姓名: %s, 性别: %s\n", id, info["name"], info["sex"])
}

补充:
- 删除的时候如果找不到对应的key,不会有任何报错
- 如果我们要删除所有的key我们需要遍历key进行删除,或者用
map = make(...),make一个新的让原来的成为垃圾,被gc回收 - map遍历只能用for-range
map切片
切片的数据类型如果是map,这样使用则map个数就可以动态变化了。
来个例子:使用map来记录工艺藏品的信息:id和quality,也就是说一个工艺藏品是一个map,并且妖怪的个数可以动态的增加。
既然可以动态增加,那我来写一个试试
var craftedCollectibles []map[string]string
craftedCollectibles = make([]map[string]string, 2)
if craftedCollectibles[0] == nil {
craftedCollectibles[0] = make(map[string]string, 2)
craftedCollectibles[0]["id"] = "Heart of Africa"
craftedCollectibles[0]["quality"] = "red"
}
if craftedCollectibles[1] == nil {
craftedCollectibles[1] = make(map[string]string, 2)
craftedCollectibles[1]["id"] = "Tears of the Ocean"
craftedCollectibles[1]["quality"] = "red"
}
if craftedCollectibles[2] == nil {
craftedCollectibles[2] = make(map[string]string, 2)
craftedCollectibles[2]["id"] = "Tears of the Ocean"
craftedCollectibles[2]["quality"] = "red"
}

?怎么报错了???不是可以动态增加吗
那作为切片是不是要追加要通过一些手段?没错就是append函数
craftedCollectibles = append(craftedCollectibles, map[string]string{
"id": "Tank model",
"quality": "red",
})
我们再来看看

map排序
a := map[int]string{
3: "three",
1: "one",
2: "two",
5: "five",
4: "four",
}
var keys []int
for k, _ := range a {
keys = append(keys, k)
}
sort.Ints(keys)
fmt.Println("按 key 升序输出:")
for _, k := range keys {
fmt.Printf("%d: %s\n", k, a[k])
}
?不知道sort.Ints啥意思?自己点开看。
注意事项和细节
1.map是引用类型,遵守引用传递的机制,在一个函数接受了map,修改后会直接修改map的数值
2.map容量打倒后,再想map增加元素,会自动扩容,不会发生panic,map可以动态增长键值对
3.map的value也可以用结构体。
比如
type User struct {
Name string
Age int
Email string
}
func main() {
users := make(map[string]User)
users["alice"] = User{"Alice", 28, "alice@example.com"}
users["bob"] = User{Name: "Bob", Age: 32}
fmt.Println(users["alice"].Name)
}
小案例:
要求:
- 使用map[string]map[string]sting 的map类型
- key:表示用户名,是唯一的,不可以重复
- 如果某个用户名存在,就将其密码修改”888888”,如果不存在就增加这个用户信息,(包括昵称nickname和密码pwd)。
- 编写一个函数modifyUser(users map[string]map[string]sting,name string)完成上述功能
package main
import "fmt"
func modifyUser(users map[string]map[string]string, name string) {
if userMap, exists := users[name]; exists {
userMap["pwd"] = "888888"
fmt.Printf("用户 %s 已存在,密码已更新为 888888\n", name)
} else {
users[name] = map[string]string{
"nickname": "default_user",
"pwd": "888888",
}
fmt.Printf("用户 %s 不存在,已新增\n", name)
}
}
func main() {
users := make(map[string]map[string]string)
modifyUser(users, "alice")
modifyUser(users, "bob")
modifyUser(users, "alice")
fmt.Println("\n最终用户数据:")
for username, userInfo := range users {
fmt.Printf("用户名: %s\n", username)
fmt.Printf(" 昵称: %s\n", userInfo["nickname"])
fmt.Printf(" 密码: %s\n", userInfo["pwd"])
fmt.Println("---")
}
}










