概述
Go中的Map是一个key(索引)和value(值)的无序集合,主要是查询方便,时间复杂度O(1)!Go Map中value的类型可以随意,但key的类型是有说法的!- 注意:
Map是无序的,而且不能保证每次打印的顺序都是相同的!
重要提示
Go 内置的 Map 不是线程安全的!当有两个线程(协程) Goroutines,同时对一个 Map 进行操作,是会报错的!
如果在并发编程的情景下,想要使用 Map,需要使用:
var syncMap sync.Map
哪些类型可作为 Map Key
可被比较的类型都可以作为
Map key!基本是固定的值,可被Hash的,才可以当作key!
可作为 Map key 的类型有:
- 可比较类型可以用作映射键,包括
bool布尔类型,int数字类型,byte字符类型,pointer指针类型,channel通道类型和interface接口类型。 - 可哈希化的类型也可以用作映射键,包括
string字符串类型和指向数组的指针类型。 struct结构类型可以用作映射键,但其中包含的字段必须是可比较的和可哈希的类型。array数组类型可以用作映射键,但数组中的元素类型必须是可比较的和可哈希的类型。
不能作为 Map key 的类型有:
slice,因为切片是可变长度的。Map,因为映射是引用类型,不能用作映射键。function,因为函数是不可比较的类型。
Map 初始化与赋值
Map 的初始化方式
func main() {
var users = map[string]string{
"鸣人": "下忍",
"佐助": "叛忍",
"小樱": "中忍",
}
fmt.Println(users)
}
func main() {
// 使用make初始化
users := make(map[string]string)
// 设置k-v
users["鸣人"] = "下忍"
users["佐助"] = "叛忍"
users["小樱"] = "中忍"
fmt.Println(users)
}
Map 容量
-
语法:
make(map[keytype]valuetype, cap) -
说明:
map的初始容量capacity并非初始化必要的参数。- 和数组不同,
map可以根据新增的key-value对动态的伸缩,因此它不存在固定长度或最大限制。 - 当
map增长到容量上限的时候,如果再增加新的key-value对,map的大小会自动加1。 - 出于性能的考虑,对于大的
map或者会快速扩张的map,即使只是大概知道容量,建议显性的标注。 map是不可以使用cap()内置方法来查看容量的!
Map 访问元素
func main() {
fmt.Println(users["卡卡西"])
}
Map 的 for 循环
func main() {
// 遍历方式1
for k, v := range users {
fmt.Println(k, v)
}
// 遍历方式2
for k := range users {
fmt.Println(k, users[k])
}
}
判断 Map 中是否存在元素
啰嗦写法
func main() {
// 是否存在
d, ok := users["卡卡西"]
if !ok {
fmt.Println("not find")
} else {
fmt.Println("find", d)
}
}
简洁写法
func main() {
// 这样的写法,ok变量的作用域在条件句中
if _, ok := users["卡卡西"]; !ok {
fmt.Println("not find")
} else {
fmt.Println("find")
}
}
删除 Map 元素
func main() {
// 即便删除不存在的k-v,也是不会报错的,可以放心使用
delete(users, "卡卡西")
}