map是go内置类型,使用key关联value

特点

  • map是无序的, 每次打印出来的map都会不一样,不能通过index获取,必须通过key获取
  • 长度是不固定的,也slice一样,是引用类型
  • 内置的len同样适用于map,返回map拥有的key数量
  • key可以是比较的类型:布尔、整数、浮点、复杂型、字符串型

使用

有三种定义方式:

  1. var map_variable
  2. make(map[key_dta_type]value_data_type)
  3. rating := map[string]float32{"C": 5, "GO": 4.5, "Python": 4.5}

map没有初始化的话, 是 nil map,不能用来存放键值对
即:

  • nil map == map[kType]vType(nil)
  • 初始化 == 分配内存

**

创建

map的秘密 - 图1

检查

获取key对应的 value,

  1. map[key]

但是当 key 如果不存在时,我们会得到该 vlaue值顾炎武的默认值(零值),比如string是空字符串, int是0,但是程序不会报错。

所以我们可以使用 ok-idiom 获取值,可知道 key/value是否存在

  1. value, ok :=`map[key]

修改

  1. map[1] = "xxx"

删除

  1. func delete(m map[Type]Type1, key Type)

delete内置函数从映射中删除具有指定键(m[key])的元素。如果m是nil,或者不存在这样的元素,则delete是no-op。

遍历

for range

  1. map1 := make(map[int]string)
  2. map1[1] = "honhaier"
  3. map1[2] = "baigujing"
  4. for k, v range map1 {
  5. fmt.Println(k, v)
  6. }

如何有序的遍历 map
取出 key,排序后, 再输出 对应的vlaue

  1. keys := make[]int, 0, len(map1)
  2. fmt.Println(keys)
  3. for k, _ := range map1 {
  4. keys = append(keys, k)
  5. }
  6. fmt.Println(keys)
  7. sort.Ints(keys) // 根据 int 排序
  8. fmt.Println(kyes)
  9. for _, key := range keys {
  10. fmt.Println(key, map1[key])
  11. }
  12. # 按字符排序
  13. s1 := []stirng{"Apple", "Window", "Orange", "abc", "隔壁老王", "acd"}
  14. fmt.Println(s1)
  15. sort.Strings(s1) // 按字符排序
  16. fmt.Println(s1)

结合slice

map结合slice使用

  1. /*
  2. * @Author: fuzhong
  3. * @LastEditTime: 2019-10-30 17:25:03
  4. */
  5. package main
  6. import "fmt"
  7. func main() {
  8. map1 := make(map[string]string)
  9. map1["name"] = "隔壁老王"
  10. map1["age"] = "30"
  11. map1["sex"] = "男性"
  12. map1["address"] = "深圳xx区xx路"
  13. fmt.Println(map1) // map[address:深圳xx区xx路 age:30 name:隔壁老王 sex:男性]
  14. map2 := make(map[string]string)
  15. map2["name"] = "小明"
  16. map2["age"] = "22"
  17. map2["sex"] = "女性"
  18. map2["address"] = "上海xx区xx路"
  19. fmt.Println(map2)
  20. map3 := map[string]string{"name": "ruby", "age": "33", "sex": "男性", "address": "深圳宝安西乡"}
  21. fmt.Println(map3)
  22. }

并发

  • read-only 线程安全
  • RW 线程不安全
  1. func main() {
  2. fmt.Println("并发读写map")
  3. m := make(map[int]int)
  4. go func() {
  5. for {
  6. m[1] = 1
  7. }
  8. }()
  9. go func() {
  10. for {
  11. _ = m[1]
  12. }
  13. }()
  14. for {
  15. }
  16. }
  17. /*
  18. output
  19. D:\projects\go\demo>go run main.go
  20. Hello world!
  21. 并发读写map
  22. fatal error: concurrent map read and map write // error
  23. goroutine 7 [running]:
  24. runtime.throw(0x4d3782, 0x21)
  25. D:/go/src/runtime/panic.go:1116 +0x79 fp=0xc00003df80 sp=0xc00003df50 pc=0x432889
  26. runtime.mapaccess1_fast64(0x4b3c40, 0xc00006a330, 0x1, 0xc000086048)
  27. D:/go/src/runtime/map_fast64.go:21 +0x19d fp=0xc00003dfa8 sp=0xc00003df80 pc=0x40ff7d
  28. main.main.func2(0xc00006a330)
  29. D:/projects/go/demo/main.go:68 +0x47 fp=0xc00003dfd8 sp=0xc00003dfa8 pc=0x49e3e7
  30. runtime.goexit()
  31. D:/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00003dfe0 sp=0xc00003dfd8 pc=0x45d241
  32. created by main.main
  33. D:/projects/go/demo/main.go:66 +0x125
  34. goroutine 1 [runnable]:
  35. main.main()
  36. D:/projects/go/demo/main.go:72 +0x126
  37. goroutine 6 [runnable]:
  38. main.main.func1(0xc00006a330)
  39. D:/projects/go/demo/main.go:62 +0x47
  40. created by main.main
  41. D:/projects/go/demo/main.go:60 +0x103
  42. exit status 2
  43. */

并发读写需求,可以使用 sync.Map

  1. type Map struct {
  2. mu Mutex
  3. // read contains the portion of the map's contents that are safe for
  4. // concurrent access (with or without mu held).
  5. //
  6. // The read field itself is always safe to load, but must only be stored with
  7. // mu held.
  8. //
  9. // Entries stored in read may be updated concurrently without mu, but updating
  10. // a previously-expunged entry requires that the entry be copied to the dirty
  11. // map and unexpunged with mu held.
  12. read atomic.Value // readOnly
  13. // dirty contains the portion of the map's contents that require mu to be
  14. // held. To ensure that the dirty map can be promoted to the read map quickly,
  15. // it also includes all of the non-expunged entries in the read map.
  16. //
  17. // Expunged entries are not stored in the dirty map. An expunged entry in the
  18. // clean map must be unexpunged and added to the dirty map before a new value
  19. // can be stored to it.
  20. //
  21. // If the dirty map is nil, the next write to the map will initialize it by
  22. // making a shallow copy of the clean map, omitting stale entries.
  23. dirty map[interface{}]*entry
  24. // misses counts the number of loads since the read map was last updated that
  25. // needed to lock mu to determine whether the key was present.
  26. //
  27. // Once enough misses have occurred to cover the cost of copying the dirty
  28. // map, the dirty map will be promoted to the read map (in the unamended
  29. // state) and the next store to the map will make a new dirty copy.
  30. misses int
  31. }

使用

  1. n := sync.Map{}
  2. n.Store("a", 111)
  3. n.Store("b", 222)
  4. // fmt.Println(n)
  5. fmt.Printf("%#v", n)