map声明语法为map[K]V,其中K和V分别对应key和value。map中所有的key都有相同的类型,所有的value也有着相同的类型,但是key和value之间可以是不同的数据类型。
map中的K对应的key必须是支持==比较运算符的数据类型,比如 整数,浮点数,指针,数组,结构体,接口等。 而不能是 函数,字典,切片这些类型,可以通过测试key是否相等来判断是否已经存在。

声明&创建

  1. var 变量名称 map[key_type]value_type

注意声明map类型是不会分配内存的。初始化需要make,才会分配内存

make函数

内置的make函数可以创建一个map:

  1. //map_variable := make(map[key_data_type]value_data_type)
  2. ages := make(map[string]int) // mapping from strings to ints

map字面量

我们也可以用map字面值的语法创建map,同时进行数据的初始化

  1. ages := map[string]int{
  2. "alice": 31,
  3. "charlie": 34,
  4. }

map操作

查找

Map中的元素通过key对应的下标语法访问:

  1. ages["alice"] = 32
  2. fmt.Println(ages["alice"]) // "32"

当从一个 map 中取值时,可选的第二返回值指示这个键是在这个 map 中。这可以用来消除键不存在和键有零值,像 0 或者 “” 而产生的歧义。第一个返回值是键的值;第二个返回值标记这个键是否存在

  1. package main
  2. import "fmt"
  3. func main() {
  4. m := map[string]int{"one": 1}
  5. if v,ok := m["one"];ok{
  6. fmt.Println("key one exist",v)
  7. }
  8. if v,ok := m["two"];!ok {
  9. fmt.Println("key two not exist",v)
  10. }
  11. }

执行结果如下,如果只对m[“two”]只获取第一个值,就会导致我们不知道是真的存在一个为零值的键值对呢,还是说这个键值对就不存在。

  1. key one exist 1
  2. key two not exist 0

删除

delete函数可以删除元素:

  1. delete(ages, "alice") // remove element ages["alice"]

遍历

使用range风格的for循环实现,

  1. package main
  2. import "fmt"
  3. func main() {
  4. scores := map[string]int{"chinese": 102, "math": 136, "english": 115}
  5. for k, v := range scores {
  6. fmt.Printf("key: %s, value: %d\n", k, v)
  7. }
  8. for k := range scores {
  9. fmt.Printf("key: %s\n", k)
  10. }
  11. for _, v := range scores {
  12. fmt.Printf("value: %d\n", v)
  13. }
  14. }

打印结果如下,如果只获取key,是不需要使用占用符。

  1. key: chinese, value: 102
  2. key: math, value: 136
  3. key: english, value: 115
  4. key: chinese
  5. key: math
  6. key: english
  7. value: 136
  8. value: 115
  9. value: 102

range对Go语言的map做遍历访问时,每次遍历map的返回的结果可能都不相同,如果需要按照顺序遍历key/value对,可以先对key进行排序,具体的实现方式可以使用sort包的Strings函数对字符串slice进行排序。

  1. import (
  2. "fmt"
  3. "sort"
  4. )
  5. func main() {
  6. m := make(map[string]string)
  7. m["hello"] = "echo hello"
  8. m["world"] = "echo world"
  9. m["go"] = "echo go"
  10. m["is"] = "echo is"
  11. m["cool"] = "echo cool"
  12. sorted_keys := make([]string, 0)
  13. for k, _ := range m {
  14. sorted_keys = append(sorted_keys, k)
  15. }
  16. sort.Strings(sorted_keys)
  17. for _, k := range sorted_keys {
  18. fmt.Printf("k=%v, v=%v\n", k, m[k])
  19. }
  20. }
  21. }

函数传递

map是引用类型,函数间传递Map是不会拷贝一个该Map的副本的,如果一个函数对Map做了修改,那么这个Map的所有引用,都会感知到这个修改。

  1. package main
  2. import "fmt"
  3. func main() {
  4. m := map[string]int{"one": 1}
  5. fmt.Println("key one before ",m["one"])
  6. modifyMap(m)
  7. fmt.Println("key one after ",m["one"])
  8. }
  9. func modifyMap(m map[string]int) {
  10. m["one"] = 2
  11. }

执行结果

  1. key one before 1
  2. key one after 2

并发map

https://github.com/orcaman/concurrent-map