Go Map

#### Go map 
***如果生命是一道墙,那么声声必有回响***
上一节我们学习了数组与切片,学习的还是基础部分, 高级部分有二维数组,多维数组...;
在这里先不写高级部分,高级部分与初级部分并没有太大区别,一个是多维切片,在每一维使用前都需要make,第二个是遍历时需要多层循环;
##### map
在 Go 中map 是key:value 数据结构,类似python 中的字典;
基本语法:
var 变量名 map[keyType]valueType
其中key 可以是如下类型:
bool, 数字,string, 指针, channel,同样还可以是包含前几个类型的接口,结构体,数组;
不过一般开发使用中key 通常为int,string;
key 需要满足可以使用== 判断,所以slice,map,函数这三个类型不可以作为map 的key ;
value 的数据类型同key 一样, 通常为数字,string, map,struct;
案例:
var a map[string]string 
var b map[int]string 
var c map[string]map[int]string 
var d map[string]int

  


map 是引用类型和slice 同样,声明或定义是不会分配内存,初始化都需要make 才能使用;
package main

import "fmt"

func main(){
   var a map[string]string
   a = make(map[string]string)
   a["01"] = "01"
   a["02"] = "02"
   a["03"] = "03"
   a["01"] = "04"
   fmt.Println(a)
}

  


1. map 在使用前需要make ;
2. map 的key 不能重复,如果重复则key 的值为最后一次赋的值 ;
3. map 是无序的,所以如果需要对map 排序,则需要对key 进行排序 ;
---
##### map 的声明和初始化方式
package main

import "fmt"

func main(){
   // 1. 先声明,再make ,最后使用
   var a map[string]string
   a = make(map[string]string)
   a["01"] = "01"
   fmt.Println(a)
   // 2. 直接使用类型推导
   b := make(map[string]string)
   b["01"] = "01"
   fmt.Println(b)
   // 3. 字面量方式
   var c = map[string]string{
      "01":"01",
   }
   fmt.Println(c)
}

  


##### map 的增删改查
map 的增加和更改
map[key] = value // 如果map 内不存在key 则属于添加操作,否则属于更改操作;
package main

import "fmt"

func main(){
   // 1. 先声明,再make ,最后使用
   var a map[string]string
   a = make(map[string]string)
   // 增加操作
   a["01"] = "01"
   a["02"] = "02"
   // 更改操作
   a["01"] = "10"
   fmt.Println(a) // map[01:10 02:02]
}

  


map 删除
delete(map,key) ,delete 是内置函数,如果key 存在则会删除这对key:value,如果key 不存在,则不会操作,也不会报错;
package main

import "fmt"

func main(){
   // 1. 先声明,再make ,最后使用
   var a map[string]string
   a = make(map[string]string)
   // 增加操作
   a["01"] = "01"
   a["02"] = "02"
   // 更改操作
   a["01"] = "10"
   fmt.Println(a) // map[01:10 02:02]
   // 删除已经存在的key
   delete(a,"02")
   // 删除不存在的key 
   delete(a,"10")
}

  


---
注意: 在Go 中没有专门的函数可以一次性删除map 中所以的key, 也就是说没有办法一次性清空map,
如果需要删除所有的key, 则需要遍历map , 一个一个删除; 另一个办法则是让gc 回收: map = make(map[keyType][valueType]);

map 查找
val,res = map[key]
如果map 中存在key 则返回value,同时返回res=true,否则不会返回value,res=false;
package main

import "fmt"

func main(){
   // 1. 先声明,再make ,最后使用
   var a map[string]string
   a = make(map[string]string)
   // 增加操作
   a["01"] = "01"
   a["02"] = "02"
   var value string
   var res bool
   value,res = a["01"]
   if res {
      // 如果有这个key
      fmt.Println("key:01 value:",value)
   } else {
      // 如果没有这个key
      fmt.Println("no value",value)
   }
   value,res = a["10"]
   if res {
      // 如果有这个key
      fmt.Println("key:10 value:",value)
   } else {
      // 如果没有这个key
      fmt.Println("no value",value)
   }
}

  


##### map 的遍历
map 的遍历方式可以使用for-range 方式
package main

import "fmt"

func main() {
   // 1. 普通的map
   var a map[string]string
   a = make(map[string]string)
   // 增加操作
   a["01"] = "01"
   a["02"] = "02"
   for key,value := range a {
      fmt.Println(key+"=",value)
   }
   // map 的value 还是一个map
   var b map[string]map[string]string
   b = make(map[string]map[string]string)
   b["01"] = map[string]string{"001":"0001"} // 第二层这里使用的是字面量方式
   // 也可以使用这样的方式
   c := make(map[string]string)
   c["002"] = "0002"
   b["02"] = c
   fmt.Println(b)
   // 复杂map 的遍历
   for key,value := range b {
      for key2,value2 := range value {
         fmt.Printf("first key=%s,first value=%v | second key=%s,second value=%s\n",key,value,key2,value2)
      }
   }
}

  


##### map 的长度使用len 函数
##### map 类型的切片
如果切片的数据类型是map , 那么map 的个数就可以动态变化了,这个在json 中比较常用,json 序列化和反序列化后面会学习到;
package main

import "fmt"

func main() {
   // 声明切片的类型为map
   var arr []map[string]string
   // 声明一个map 类型
   var a map[string]string
   // 初始化map
   a = make(map[string]string)
   // map 赋值
   a["01"] = "01"
   // 初始化切片
   arr = make([]map[string]string,0) // append 函数底层会检查是否make ,所以这一行可以省略;
   arr = append(arr,a)
   // 再添加一个map
   var b map[string]string
   b = make(map[string]string)
   b["001"] = "001"
   arr = append(arr,b)
   fmt.Println(arr)
}

  


##### map 排序
在上面我们知道了,map 本身是无序的,所以排序需要先对key 排序,然后按排序后的key 输出map即可;
package main

import (
   "fmt"
   "sort"
)

func main() {
   var a map[string]string
   a = make(map[string]string)
   a["01"] = "01"
   a["first"] = "first"
   a["second"] = "second"
   a["third"] = "third"
   a["fourth"] = "fourth"
   // 输出是无序的,多运行几次即可看到
   for k,v := range a {
      fmt.Println(k,v)
   }
   // 对map 排序,需要先对key 排序
   var keySlice []string
   for key,_ := range a {
      keySlice = append(keySlice,key)
   }
   // 排序
   // 排序前
   fmt.Println(keySlice)
   sort.Strings(keySlice)
   // 排序后
   fmt.Println(keySlice)
   // 按排序后的key 输出map
   for _,key := range keySlice {
      fmt.Println(key,a[key])
   }
}

  


map 的使用注意事项
1. map 是引用类型,遵守引用类型传递机制,在函数内部修改后,会改变原来的值 ;
2. map 会自动扩容,可以动态增长;
package main

import "fmt"

func test01(a map[string]string){
   // 新增加一个key:value
   a["02"]    = "02"
}
func main() {
   var a map[string]string
   a = make(map[string]string)
   a["01"] = "01"
   a["first"] = "first"
   // 传入函数前
   fmt.Println(a) //map[01:01 first:first]
   // 传入函数后
   // 可以看出map 是引用类型,遵守引用传递机制
   test01(a)
   fmt.Println(a) //map[01:01 first:first 02:02]
}

  最新文章会在微信公众号,欢迎关注学习交流

posted @ 2019-09-04 14:26  mail_maomao  阅读(171)  评论(0编辑  收藏  举报