golang map
1.声明
var 变量名 map[keytype]valuetype
golang中的map的key可以是很多类型,比如bool,数字,string,指针,channel还可以是前面几个类型的接口,结构体,数组,通常为int,string。
注意:
1.slice,map还有function不可以做key,因为这几个没法用==来判断。
2.声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用,若size省略则会分配一个小的起始大小。但是size是随着使用而自动增加的。
3.map的key是不可以重复的,如果重复了,则后面的值会覆盖前面的值
3.golang的map中的元素是无序的
func main() {
//map的声明和注意事项 var a map[string]string //在使用map前,需要先make,make的作用就是给mao分配数据空间,下面分配了10个长度
a = make(map[string]string, 10) //map[no1:武松 no2:吴用 no3:吴用] a["no1"] = "宋江" a["no2"] = "吴用" a["no1"] = "武松" //替换掉了"宋江" a["no3"] = "吴用" fmt.Println(a) }
2.使用
1)声明+make
var cities map[string]string
cities = map(map[string]string, 10)
2)声明时make
var cities = make(map[string]string, 10)
3)声明,直接赋值
var cities map[string]string = map[string]string{"node4":成都}
cities["no1"] = "成都"
func main() { //第一种方式 //map的声明和注意事项 var a map[string]string //在使用map前,需要先make,make的作用就是给mao分配数据空间 a = make(map[string]string, 10) //map[no1:武松 no2:吴用 no3:吴用] a["no1"] = "宋江" a["no2"] = "吴用" a["no1"] = "武松" //替换掉了"宋江" a["no3"] = "吴用" fmt.Println(a) //第二种方式 cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "添加" cities["no3"] = "上海" fmt.Println(cities) //第三种方式 //heroes := map[string]string{ var heroes map[string]string = map[string]string{ "her01": "宋江", "hero2": "卢俊义", } heroes["hero3"] = "吴用" fmt.Println(heroes) }
3.map实例
要存放3个学生信息,每个学生有name,sex和adress信息
思路:key为学号,val为map[string]string,其中val的map中存放的是name,sex和adress
func std() { student := make(map[string]map[string]string) student["stu01"] = make(map[string]string, 3) student["stu01"]["name"] = "tom" student["stu01"]["sex"] = "男" student["stu01"]["address"] = "北京长安街" student["stu02"] = make(map[string]string, 3) student["stu02"]["name"] = "jack" student["stu02"]["sex"] = "男" student["stu02"]["address"] = "上海长安街" fmt.Println(student) fmt.Println(student["stu02"]) fmt.Println(student["stu02"]["address"]) }
4.map的增删改查crud
func crud() { cities := make(map[string]string) //1.增加 cities["no1"] = "北京" cities["no2"] = "添加" cities["no3"] = "上海" //2.修改:因为no3这个key已经存在了,所以下面这句话就是修改 cities["no3"] = "上海~" fmt.Println(cities) //3.查找 //如果找到了,findRes为true,找不到为false val, findRes := cities["no3"] if findRes { fmt.Printf("有no3这个key,值为%v:\n", val) } else { fmt.Println("没有no3这个key\n") } //4.删除,delete函数删除元素 delete(cities, "no1") fmt.Println(cities) //当delete指定的key不存在,删除不会操作,也不会报错 delete(cities, "node4") fmt.Println(cities) //如果要删除map中所有的key,没有专门的函数 //1)可以遍历key逐个删除 //2)给map make一个新的空间,让原本的成为垃圾被gc回收 cities = make(map[string]string) fmt.Println(cities) }
5.map的遍历
由于map的key不一定是数字通常为string,所以不适应for循环,而使用for-range来遍历
func xh() { //简单结构map的for-range cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "添加" cities["no3"] = "上海" for k, v := range cities { fmt.Printf("k=%v,v=%v\n", k, v) } //使用双层for-range遍历一个结构比较复杂的map student := make(map[string]map[string]string) student["stu01"] = make(map[string]string, 3) student["stu01"]["name"] = "tom" student["stu01"]["sex"] = "男" student["stu01"]["address"] = "北京长安街" student["stu02"] = make(map[string]string, 3) student["stu02"]["name"] = "jack" student["stu02"]["sex"] = "男" student["stu02"]["address"] = "上海长安街" for k1, v1 := range student { fmt.Println("k1=", k1) for k2, v2 := range v1 { fmt.Printf("\t k2=%v v2=%v\n", k2, v2) } } }
6.map切片
使用map切片,使map的个数可以动态变化,效果相当于一个复合map map[int]map[string]string,但是复合map只是一个map而map切片是有多个map
案例:使用一个map来记录monster的信息name和age,也就是说一个monster对应一个map,并且妖怪的个数是可以动态增加的=>map切片
func mons() { var monsters []map[string]string //切片本身要make一次,切片make时必须要加长度 monsters = make([]map[string]string, 2) if monsters[0] == nil { //切片的数据类型为map,map还需要make一次,map make时可以不加长度 monsters[0] = make(map[string]string) monsters[0]["name"] = "牛魔王" monsters[0]["age"] = "500" } if monsters[1] == nil { //切片的数据类型为map,map还需要make一次,map make时可以不加长度 monsters[1] = make(map[string]string, 2) monsters[1]["name"] = "玉兔精" monsters[1]["age"] = "300" } //切片数量的动态增加用append(slice,map) newmonsters := map[string]string{ "name": "火云邪神", "age": "600", } monsters = append(monsters, newmonsters) fmt.Println(monsters) //[map[age:500 name:牛魔王] map[age:300 name:玉兔精]] }
7. map排序
1)golang中没有专门的方法针对map的key进行排序
2)golang中的map默认是无序的,注意也不是按照添加的顺序放的,每次遍历,得到的输出可能都不一样
3)要做map的排序,需要先将key进行排序,然后根据key的值遍历输出即可
func sortmap() { //map的排序 map1 := make(map[int]int, 4) map1[10] = 100 map1[1] = 13 map1[4] = 56 map1[2] = 90 fmt.Println(map1) //按照map的key的顺序进行排序输出 //1.先将map的key放入到切片中 //2.对切片排序 //3.遍历切片,然后按照key来输出map的值 //建立key的map切片 var keys []int for key, _ := range map1 { keys = append(keys, key) } //对keys进行排序 sort.Ints(keys) //遍历切片,按照key输出map值 for _, v := range keys { fmt.Printf("%v", map1[v]) } }
8.map的使用细节
1)map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后会直接修改原来的map
2)map容量达到后,map再增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对。而数组,只能通过append函数进行扩容而不能自动扩容
3)map的value也经常使用struct类型,更适合管理复杂的数据(比前面value是一个map更好),比如valur为student结构体
type Stu struct { Name string Age int Address string } func f1() { students := make(map[string]Stu, 10) stu1 := Stu{"tom", 18, "北京"} stu2 := Stu{"marry", 16, "上海"} students["no1"] = stu1 students["no2"] = stu2 fmt.Println(students) //遍历 for k, v := range students { fmt.Printf("学生的编号是%v\t", k) fmt.Printf("学生的名字是%v\t", v.Name) fmt.Printf("学生的年龄是%v\t", v.Age) fmt.Printf("学生的地址是%v\t", v.Address) fmt.Println() } }
9.使用map[string]map[string]string的map类型;key表示用户名,是唯一的不可用重复;如果某个用户名存在,就将其密码修改为“888888”,如果不存在就增加这个用户信息(包括昵称nickname和密码pwd);编写一个函数modifyuser(users map[string]map[string]string, name string)完成上述功能
func modifyUser(user map[string]map[string]string, name string) { if user[name] != nil { user[name]["pwd"] = "888888" } else { user[name] = make(map[string]string, 2) user[name]["nockname"] = "昵称!" + name user[name]["pwd"] = "777" } } func main() { user := make(map[string]map[string]string, 2) user["smth"] = make(map[string]string, 2) user["smth"]["nockname"] = "smth" user["smth"]["pwd"] = "9999" modifyUser(user, "TOM") modifyUser(user, "Marry") modifyUser(user, "Marry1") modifyUser(user, "Marry2") modifyUser(user, "smth") fmt.Println(user) }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?