map的使用和细节
基本语法
var 变量名 map[key-type]value-type 例如 var a map[int]string->key是int类型,value是string类型。
注意:通常key为int,string类型,而slice,map和function不可以作为Key,因为这几个没法用==来判断。
func main() { //map的声明 make的作用给map分配数据空间 var a map[string]string = make(map[string]string) a["no1"] = "宋江" a["no2"] = "吴用" a["no1"] = "武松" //key不能重读,武松会覆盖松江 a["no3"] = "吴用" fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用] //数组在声明的时候已经分配数据空间了 var arr [5]int arr[1] = 1 fmt.Println(arr) //[0 1 0 0 0] }
- map使用前一定要make。
- map的key是不能重复的,如果重复了,则以最后这个key-value为准。
- map的value是可以相同的。
- map的key-value是无序的。
- make是一个内置函数,初始map的时候分配的创建取决于size。但产生的映射长度为0。size可以省略,这种情况下可以分配一个小的大小。
map的使用方式
func main() { //方式1 声明后再分配空间 var a map[string]string a = make(map[string]string, 10) a["no1"] = "宋江" a["no2"] = "吴用" a["no1"] = "武松" a["no3"] = "吴用" fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用] //方式2 类型判断直接make cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //map[no1:北京 no2:天津 no3:上海] //方式3 初始化的时候就赋值 var heroes map[string]string = map[string]string{ "hero1": "猪猪侠", "hero2": "钢铁侠",//这里结尾也要有逗号 } fmt.Println(heroes) //map[hero1:猪猪侠 hero2:钢铁侠] }
map的增删查改操作:
- map的增加和更新:map["key"]=value //如果Key没有则增加,如果Key存在就是修改。
- map的删除:delete(map,key),delete是一个内置函数,如果key存在,就删除key-value,如果Key不存在,不做任何变化,也不会报错。
func main() { //定义个map var a map[string]string a = make(map[string]string, 10) a["no1"] = "宋江" a["no2"] = "吴用" a["no1"] = "武松" //替换no1的value a["no3"] = "吴用" a["no3"] = "吴用1111" //替换no3的value fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用1111] //删除 delete(a, "no3") fmt.Println(a) //map[no1:武松 no2:吴用] }
说明:如果要清空整个map我们可以遍历整个map依次删除key。或者把map的指向一个新的空间,那么以前的Map空间会被GC回收。
- map的查找: value,boole := map[key]
//引用上个代码块的map变量名是a value, b := a["no1"] if b { fmt.Println("no1的值是", value) } else { fmt.Println("no1的值是空的") }
map的遍历:
func main() { //定义个map var a map[string]string a = make(map[string]string, 10) a["no1"] = "宋江" a["no2"] = "吴用" a["no3"] = "吴用" //遍历map只能用for range for key, value := range a { fmt.Println("key=", key, "value=", value) } //定义一个map stus := make(map[string]map[string]string) stus["no1"] = make(map[string]string, 3) stus["no1"]["name"] = "张三" stus["no1"]["sex"] = "男" stus["no1"]["address"] = "北京长安街" stus["no2"] = make(map[string]string, 3) stus["no2"]["name"] = "小红" stus["no2"]["sex"] = "女" stus["no2"]["address"] = "上海红灯区" for k1, v1 := range stus { fmt.Println("k1=", k1) for k2, v2 := range v1 { fmt.Println("k2=", k2, "v2=", v2) } } }
map切片
切片的数据类型如果是Map,那么这样的数据结构就是map切片,这样使用则map个数就可以动态变化的。
func main() { //map切片 其实外层就是一个切片 里面的数据是map[string]string类型 monsters := make([]map[string]string, 2) //增加数据 if monsters[0] == nil { //切片的第一个元素是空的 那么就放入信息 monsters[0] = make(map[string]string) monsters[0]["name"] = "牛魔王" monsters[0]["age"] = "500岁" } if monsters[1] == nil { monsters[1] = make(map[string]string) monsters[1]["name"] = "玉兔精" monsters[1]["age"] = "100岁" } //monsters切片分配了2个内存空间 如果要继续加元素需要append函数 monsters = append(monsters, map[string]string{ "name": "红孩儿", "age": "200岁", }) fmt.Println(monsters)//[map[age:500岁 name:牛魔王] map[age:100岁 name:玉兔精] map[age:200岁 name:红孩儿]] }
map的排序
- golang中的map默认是无序的,也就是说不是按添加的顺序存放的,每次遍历,得到的输出可能不一样。
- 正对上面的问题,其实解决思路也很简单:定义一个切片存放map的key。 var keys = []int
3 对切片进行排序,使用内置函数sort.Ints(keys),keys的定义的切片变量名字,类似是[]int
4 遍历切片,根据key找到map中的value。
func main() { //定义一个map m := make(map[int]int) m[10] = 100 m[1] = 13 m[4] = 56 m[8] = 90 fmt.Println(m) //定义一个切片 var keys []int //把map的key放入切片中 for k, _ := range m { keys = append(keys, k) } //遍历切片按key输出map的value for _, k := range keys { fmt.Printf("%v:%v \n", k, m[k]) } }
map细节
- map是引用类型,遵守引用传递的机制,在一个函数接收Map,修改后会直接修改原来的值。
- map可以动态增长容量。
- map的value也经常使用struct类型,更适合管理复杂的数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)