基本介绍
Map 是一种无序的键值对的集合。
基本使用
初始化
初始化 Map 可以使用 make 函数,也可以使用字面量的方式直接初始化值。
// 创建一个空的 Map
m1 := make(map[string]int)
// 使用字面量的方式
m2 := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
fmt.Println(m1) // map[]
fmt.Println(m2) // map[apple:1 banana:2 orange:3]
设置元素
使用 Map 名加键名的方式,可以设置一个键值对,如果有值则修改,没有则新建一个键值对。
// 修改原有的值
m2["apple"] = 4
fmt.Println(m2) // map[apple:4 banana:2 orange:3]
// 设置新的值
m2["apple2"] = 5
fmt.Println(m2)// map[apple:4 apple2:5 banana:2 orange:3]
获取值
通过键名获取 Map 相对应的键值,获取键值的同时也可以获取键是否存在。
// 直接获取键值
value := m2["apple"]
fmt.Println(value) // 4
// 获取键值,并获取是否存在
value1,ok1 := m2["apple"]
fmt.Println(ok1) // true
fmt.Println(value1) // 4
// 获取键值,并获取是否存在
value2,ok2 := m2["apple3"]
fmt.Println(ok2) // false
fmt.Println(value2) // 0
获取 Map 元素数量
可以通过 len 函数获取 Map 元素的数量
m3 := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
"apple1": 3,
"apple2": 3,
"apple3": 3,
}
fmt.Println(len(m3)) //6
删除元素
- go 提供了一个用来删除 Map 元素的函数,delete 函数,传递 Map 和需要删除的键名。
- go 没有提供清空整个 Map 的方法,需要清空可以将 nil 赋值给 Map
delete(m3,"apple1")
delete(m3,"apple2")
delete(m3,"apple3")
fmt.Println(m3)// map[apple:1 banana:2 orange:3]
// 清空map
m3 = nil
fmt.Println(m3) // map[]
遍历 Map
- 遍历 map 可以使用 for range 语法来遍历 Map
- 不过 map 是无序的,不能保证输出顺序是固定的
for k,v := range m3{
fmt.Printf("Key:%s Result:%d\n",k,v)
}
引用类型
map 和切片一样也是引用类型,如果直接用 = 赋值,两者其实指向的 map 是一样的
m4 := m3
fmt.Println(m4) // map[apple:1 banana:2 orange:3]
m3["apple"] = 10
fmt.Println(m3) // map[apple:10 banana:2 orange:3]
fmt.Println(m4) // map[apple:10 banana:2 orange:3]
可以看到把 m3 赋值给 m4 之后,修改了 m3 的某个key ,m4 也一起改动了
注意事项
- Map 是引用类型,注意赋值或者传参给函数的时候实际都是相同的 Map。
- Map 的键必须是可比较的类型,如整数、字符串和指针等,但是切片、函数和结构体等类型是不可比较的,因此不能用作键。
- Map 中的元素是无序的,这意味着遍历 Map 时,元素的顺序可能会随机改变。
- Map 的容量是动态变化的,它会自动调整容量以适应新的元素。
- 如果使用未初始化的 Map,会导致运行时错误。需要使用 make() 函数来初始化 Map。
- Map 在并发环境下不是安全的。如果需要在并发环境下使用 Map,需要使用 sync 包中提供的锁机制来保护 Map。
- Map 并发读写会造成致命错误,所以在并发环境中要想清楚使用 Map 的场景,和加锁的地方。