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] }
最新文章会在微信公众号,欢迎关注学习交流
每天进步一点点!加油