8.1 介绍

map也是引用类型
声明:var map1 map[int]string
map在声明的时候不需要声明长度,因为它是可以动态增长的。
未初始化的map的值是nil。
和其他语言的字典的作用类似,以键值对key:value作为元素。
key可以是string,int,float,指针,接口等类型,数组切片结构体等不行,value可以任意类型。
map不存在固定长度,或最大容量,但定义的时候是可以指定初始容量的。

  1. map1 := make(map[int]string, 500)

8.2 map的操作

要获取一个key的值,可以使用val1 := map1[key1],获取key1对应的值,如果这个key1不存在,则返回空值。但是如果这个key1的值就是空值呢?
可以使用isPresent解决上述困扰。

  1. package main
  2. import "fmt"
  3. func main() {
  4. map1 := map[int]string{1: "a", 2: "b", 3: "c"}
  5. val1 := map1[4]
  6. fmt.Println(val1) //字符串空值""
  7. val2, isPresent := map1[4]
  8. if isPresent == false {
  9. fmt.Println("key不存在")
  10. } else {
  11. fmt.Println(val2)
  12. }
  13. }

由此可以拓展到,如果你这是想判断某个key存不存在,那么可以:

  1. if _,ok := map[key]; ok{
  2. ...
  3. }

使用for range结构来循环遍历map。

  1. package main
  2. import "fmt"
  3. func main() {
  4. map1 := map[int]string{1: "a", 2: "b", 3: "c"}
  5. for key, value := range map1 {
  6. fmt.Println(key, value)
  7. }
  8. }
  9. // 2 b
  10. // 3 c
  11. // 1 a

可以看到,输出并不是按照123这样的顺序输出的,说明map是无序的。
map的本质其实是散列表,map的增容回导致重新进行散列,导致map的遍历结果在扩容前后不可靠。

8.3 map类型的切片

想要得到一个map类型的切片需要两次make,第一次分配切片,第二次才分配切片的元素。

  1. package main
  2. import "fmt"
  3. func main() {
  4. sli := make([]map[int]int, 5) //初始化map类型的切片
  5. for i := range sli {
  6. sli[i] = make(map[int]int, 10) //初始化切片的元素
  7. sli[i][1] = 1 //给元素赋值
  8. }
  9. fmt.Println(sli) //得到5个元素[map[1:1] map[1:1] map[1:1] map[1:1] map[1:1]]
  10. }

8.4 map的排序

map是无序的,无论是key还是value都是无序的。
如果想要排序map,需要到切片,把key或value拷贝到一个切片,在切片里用sort()排序好,因为key和value是对应的,那么按照排序号的切片key来输出value,就实现了map的排序输出。

  1. package main
  2. import (
  3. "fmt"
  4. "sort"
  5. )
  6. func main() {
  7. map1 := map[int]int{
  8. 1: 1,
  9. 3: 3,
  10. 2: 2,
  11. }
  12. sli1 := []int{}
  13. for k := range map1 {
  14. sli1 = append(sli1, k) //把key存到切片中
  15. }
  16. sort.Ints(sli1) //切片升序
  17. for _, i := range sli1 {
  18. fmt.Println(i, map1[i])
  19. }
  20. }