Map

    使用关键字 map 来声明形如:

    • 必须指定 key, value 的类型,插入的纪录类型必须匹配。
    • key 具有唯一性,插入纪录的 key 不能重复。
    • KeyType 可以为基础数据类型(例如 bool, 数字类型,字符串), 不能为数组,切片,map,它的取值必须是能够使用 进行比较。
    • ValueType 可以为任意类型。
    • 无序性。
    • 线程不安全, 一个 goroutine 在对 map 进行写的时候,另外的 goroutine 不能进行读和写操作,Go 1.6 版本以后会抛出 runtime 错误信息。

    声明和初始化

    • 使用 var 声明
    1. var cMap map[string]int // 只定义, 此时 cMap 为 nil
    2. fmt.Println(cMap == nil)
    3. cMap["北京"] = 1 // 报错,因为 cMap 为 nil
    • 使用 make
    1. cMap := make(map[string]int)
    2. cMap["北京"] = 1
    3. // 指定初始容量
    4. cMap["北京"] = 1

    说明:在使用 make 初始化 map 的时候,可以指定初始容量,这在能预估 map key 数量的情况下,减少动态分配的次数,从而提升性能。

    • 简短声明方式
    1. cMap := map[string]int{}
    2. cMap["北京"] = 1 //写
    3. code := cMap["北京"] // 读
    4. fmt.Println(code)
    5. code = cMap["广州"] // 读不存在 key
    6. fmt.Println(code)
    7. code, ok = cMap["广州"] // 检查 key 是否存在
    8. if ok {
    9. fmt.Println(code)
    10. } else {
    11. fmt.Println("key not exist")
    12. }
    13. delete(cMap, "北京") // 删除 key
    14. fmt.Println("北京")

    循环和无序性

    1. for city, code := range cMap {
    2. fmt.Printf("%s:%d", city, code)
    3. }
    1. fatal error: concurrent map writes
    2. goroutine x [running]:
    3. runtime.throw(0x10c64b6, 0x15)
    4. .....

    解决之道:

    • 对读写操作加锁
    • 使用 security map, 例如 sync.map

    map 嵌套

    1. provinces := make(map[string]map[string]int)
    2. provinces["北京"] = map[string]int{
    3. "东城区": 1,
    4. "西城区": 2,
    5. "朝阳区": 3,
    6. "海淀区": 4,
    7. }