跳到主要内容

map

map 是什么? key 类型和零值有何限制?​

  • map: key-value 映射表;
  • key 类型: 必须支持相等比较;
  • value 类型: 任意 Go 类型;
  • 零值入口: nil 状态下的读写、删除规则见本篇下一节;
func main() {
ages := map[string]int{"tom": 18}
println(ages["tom"])
}

map 的 nil 状态下哪些操作安全?​

  • 写入边界: 读取 nil map 或不存在的键会得到值类型零值;写入 nil map 会 panic,应先用 make 或字面量初始化;
  • 删除边界: delete 可以删除已有键,键不存在或 map 为 nil 时不做任何事;
var counts map[string]int
println(counts["go"]) // 0:读取 nil map 安全
delete(counts, "go") // 安全的空操作
// counts["go"] = 1 // panic:尚未初始化
counts = map[string]int{}
counts["go"] = 1 // 初始化后可以写入

如何初始化 map 并区分缺失键与零值?​

  • 存在性检查: v, ok := m[key] 中 ok 表示键是否存在,避免把不存在的键误判成显式保存的零值;
func main() {
m := make(map[string]int)
m["a"] = 1
v, ok := m["b"] // 区分 key 不存在和 value 零值
delete(m, "a") // key 不存在也安全
println(v, ok, len(m))
}

map 如何遍历? 顺序是否稳定?​

  • 遍历: range 依次产生键和值副本,顺序没有保证;需要稳定输出时先收集键、排序,再按键读取;
package main

import "fmt"

func main() {
m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
fmt.Println(k, v) // 遍历顺序不保证稳定
}
}