go-map
介绍
-
map是key-value数据结构,又称为字段或者关联数组。类似其他编程语言的集合。
-
基本语法 :
var map变量名 map[keyType]valueType
keyType:golang中的map的key可以是很多种类型:bool、数字、string、指针、channel、还可以是只包含前面几个类型的接口、结构体、数组
通常是int和string
-
slice,map还有function不可以,因为这几个没法用==来判断
-
valueType的类型和key基本相似
通常是数字、string、map、struct
-
map使用签一定要make分配空间
-
map的key不能重复,若重复,则会覆盖
-
map的value可以重复
-
map的key-value无序
-
make 映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个 小的起始大小。
func main() {
var map1 map[string]int = make(map[string]int) // 需make分配空间,否则无法使用
fmt.Printf("map1: %v\n", map1) // map1: map[]
fmt.Printf("&map1: %p\n", &map1) // &map1: 0xc0000b6010
map1["tom"] = 22
map1["jack"] = 33
map1["tom"] = 33
fmt.Printf("map1: %v\n", map1) // map1: map[jack:33 tom:33] key不重复,且无序
}
三种用法
- 先声明再make
- 既声明也make
- 声明+赋值
func main() {
// 1. 先声明再赋值
var map1 map[string]int
map1 = make(map[string]int)
map1["tom"] = 22
map1["jack"] = 33
fmt.Printf("map1: %v\n", map1) // map1: map[jack:33 tom:22]
// 2. 声明+make
var map2 map[string]int = make(map[string]int)
map2["beijing"] = 1
map2["shanghai"] = 2
map2["dalian"] = 5
fmt.Printf("map2: %v\n", map2) // map2: map[beijing:1 dalian:5 shanghai:2]
// 3. 声明+赋值
var map3 map[string]int = map[string]int{
"beijing": 1,
"shanghai": 2,
"shenzhen": 3, // , 不能省
}
map3["xiongan"] = 4
// map3 := map[string]int{"beijing": 1, "shanghai": 2, "shenzhen": 3}
fmt.Printf("map3: %v\n", map3) // map3: map[beijing:1 shanghai:2 shenzhen:3 xiongan:4]
}
studentMap := make(map[string]map[string]string)
studentMap["student1"] = make(map[string]string)
studentMap["student1"]["name"] = "tom"
studentMap["student1"]["sex"] = "man"
studentMap["student1"]["address"] = "beijing"
studentMap["student1"]["tel"] = "123456789"
studentMap["student2"] = make(map[string]string)
studentMap["student2"]["name"] = "jack"
studentMap["student2"]["sex"] = "women"
studentMap["student2"]["address"] = "shanghai"
studentMap["student2"]["tel"] = "123123123"
fmt.Printf("studentMap: %v\n", studentMap)
fmt.Printf("studentMap[\"student1\"]: %v\n", studentMap["student1"])
fmt.Printf("studentMap[\"student2\"]: %v\n", studentMap["student2"])
fmt.Printf("studentMap[\"student1\"][\"name\"]: %v\n", studentMap["student1"]["name"])
crud操作
func main() {
var map1 map[string]int = make(map[string]int)
// 1. 增加和修改
// 1.1 添加 key不存在就是添加
map1["tom"] = 22
map1["jack"] = 33
fmt.Printf("map1: %v\n", map1) // map1: map[jack:33 tom:22]
// 1.2 修改 key存在就是添加
map1["jack"] = 66
fmt.Printf("map1: %v\n", map1) // map1: map[jack:66 tom:22]
// 2. 删除 内置函数delete(map, key)
delete(map1, "tom")
fmt.Printf("map1: %v\n", map1) // map1: map[jack:66]
delete(map1, "tom") // 当不存在时,也不会报错
// 3. 清空map
// 3.1 遍历逐个删除
for k := range map1 {
delete(map1, k)
}
// 3.2 直接给map开辟一个新空间, make
map1 = make(map[string]int)
// 4. 查找 第一个返回值是 对应的值value, 第二返回值是,是否找到,若找到为true 否则为 false
val, findres := map1["no"]
if findres {
fmt.Printf("val: %v\n", val)
} else {
fmt.Println("no find")
}
}
遍历
func main() {
// map遍历
var people map[string]int = map[string]int{"tom": 22, "jack": 33, "luxy": 44}
// 1. 整体遍历
for k, v := range people {
fmt.Printf("%v: %v\t", k, v) // tom: 22 jack: 33 luxy: 44
}
fmt.Println("")
// 2. 仅遍历key 和 获取key的切片
keys := make([]string, 0, len(people))
for k := range people {
keys = append(keys, k)
fmt.Printf("k: %v\n", k)
}
// k: tom
// k: jack
// k: luxy
// 3. 内置函数len 获取map的长度
fmt.Printf("len(people): %v\n", len(people)) // len(people): 3
}
切片
func main() {
var people []map[string]string = make([]map[string]string, 1)
var people1 map[string]string = make(map[string]string)
people1["name"] = "tom"
people1["age"] = "22"
people1["address"] = "shanghai"
people = append(people, people1)
var people2 map[string]string = make(map[string]string)
people2["name"] = "jack"
people2["age"] = "33"
people2["address"] = "beijing"
people = append(people, people2)
people[0] = make(map[string]string)
people[0]["name"] = "lucy"
people[0]["age"] = "44"
people[0]["address"] = "shenzhen"
// people: [map[address:shanghai age:22 name:tom] map[address:beijing age:33 name:jack]]
fmt.Printf("people: %v\n", people)
for index, val := range people {
fmt.Printf("index: %v\n", index)
// fmt.Printf("val: %v\n", val)
for k, v := range val {
fmt.Printf("\t %v: %v \n", k, v)
}
}
// index: 0 val: map[address:shanghai age:22 name:tom]
// index: 1 val: map[address:beijing age:33 name:jack]
/*
index: 0
age: 22
address: shanghai
name: tom
index: 1
name: jack
age: 33
address: beijing
*/
}
排序
- golang中没有一个专门的方法针对map的key进行排序
- golang中的map默认是无序的,注意不是按照添加的顺序存放的,每次遍历得到的输出结果不同
- golang中的map排序,是先将key进行排序,然后根据key值遍历输入即可
import (
"fmt"
"sort"
)
func main() {
var numMap map[int]int = make(map[int]int)
numMap[3] = 33
numMap[1] = 11
numMap[4] = 44
numMap[2] = 22
numMap[5] = 55
fmt.Printf("numMap: %v\n", numMap)
// 1. 先将map的key放入到切片
// 2. 对切片进行排序
// 3. 遍历切片。按照key来输入map值
keys := make([]int, 0, len(numMap))
for k := range numMap {
keys = append(keys, k)
}
sort.Ints(keys)
fmt.Printf("keys: %v\n", keys) // keys: [1 2 3 4 5]
for _, v := range keys {
fmt.Printf("key: %v value: %v\n", v, numMap[v])
// key: 1 value: 11
// key: 2 value: 22
// key: 3 value: 33
// key: 4 value: 44
// key: 5 value: 55
}
}
注意事项
-
map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map
func main() { map1 := make(map[int]int) map1[1] = 11 map1[3] = 33 test(map1) fmt.Printf("map1: %v\n", map1) // map1: map[1:111 2:222 3:33] } func test(map1 map[int]int) { map1[1] = 111 map1[2] = 222 }
-
map的扩容达到后,再向map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对
-
map的value也经常使用struct类型,更适合管理复杂的数据(比前面value是一个map更好),比如value是Student结构体
func main() {
studentMap := make(map[int]student)
studentMap[1] = student{"tom", 11, "beijing"}
studentMap[2] = student{"jack", 22, "shanghai"}
studentMap[3] = student{"lucy", 33, "shenzhen"}
fmt.Printf("studentMap: %v\n", studentMap)
for k, s := range studentMap {
fmt.Printf("k: %v ", k)
fmt.Printf("s.name: %v ", s.name)
fmt.Printf("s.age: %v ", s.age)
fmt.Printf("s.address: %v\n", s.address)
}
}
type student struct {
name string
age int
address string
}
案例
func main() {
var userMap map[string]map[string]string = make(map[string]map[string]string)
name := "tom"
modifyUser(userMap, name)
fmt.Printf("userMap: %v\n", userMap)
// userMap: map[tom:map[nickname:nickname pwd:123456]]
modifyUser(userMap, name)
fmt.Printf("userMap: %v\n", userMap)
// userMap: map[tom:map[nickname:nickname pwd:888888]]
}
func modifyUser(users map[string]map[string]string, name string) {
v, findres := users[name]
if findres {
v["pwd"] = "888888"
} else {
v = make(map[string]string)
v["nickname"] = "nickname"
v["pwd"] = "123456"
users[name] = v
}
}