学习GO之九、MAP

  1. map 的基本介绍

map 是 key-value 数据结构,又称为字段或者关联数组。类似其它编程语言的集合, 在编程中是经常使用到

  1. map 的声明

var map 变量名 map[keytype]valuetype

  • key 可以是什么类型

    • bool, 数字,string, 指针, channel , 还可以是只 包含前面几个类型的 接口, 结构体, 数组 , 通常 key 为 int 、string 注意: slice, map 还有 function 不可以,因为这几个没法用 == 来判断
  • valuetype 可以是什么类型

    • valuetype 的类型和 key 基本一样 , 通常为: 数字(整数,浮点数),string,map,struct
  1. map 声明的举例

var a map[string]string 
var a map[string]int 
var a map[int]string 
var a map[string]map[string]string 

注意:声明是不会分配内存的,初始化需要 make ,分配内存后才能赋值和使用。

var a map[string]string //map[]
//map声明是不会分配内存的,初始化需要 make ,分配内存后才能赋值和使用
//a["n01"] = "宋江" //panic: assignment to entry in nil map
//使用前先make,分配数据空间,数组声明时候就分配

a = make(map[string]string, 10)
a["n01"] = "宋江"  //map[n01:宋江]
a["n02"] = "吴用1" //map[n01:武松 n02:吴用]
a["n01"] = "武松"  //key不能重复,会被覆盖
a["n03"] = "吴用2" //value可以

//test
//顺序问题
//map[n01:武松 n02:吴用1 n03:吴用2]
//map[n01:武松 n02:吴用1 n03:吴用2]
fmt.Println(a)

  • map 在使用前一定要 make

  • map 的 key 是不能重复,如果重复了,则以最后这个 key-value 为准

  • map 的 value 是可以相同的

  • map 的 key-value 是无序

  • make 内置函数数目

    • size可以省略,第一个表示分配的常量,第二个为容量。容量不能小于长度
  • 默认分配一个小的初始大小

  1. map 的使用

  1. 先声明 再make
  2. 声明的时候同时make
  3. 声明,直接赋值
//第一种方式
var a map[string]string //map[]
//map声明是不会分配内存的,初始化需要 make ,分配内存后才能赋值和使用
//a["n01"] = "宋江" //panic: assignment to entry in nil map
//使用前先make,分配数据空间,数组声明时候就分配

a = make(map[string]string, 10)
a["n01"] = "宋江"  //map[n01:宋江]
a["n02"] = "吴用1" //map[n01:武松 n02:吴用]
a["n01"] = "武松"  //key不能重复,会被覆盖
a["n03"] = "吴用2" //value可以

//test
//顺序问题
//map[n01:武松 n02:吴用1 n03:吴用2]
//map[n01:武松 n02:吴用1 n03:吴用2]
fmt.Println(a)

//第二种方式 常用
cities := make(map[string]string)
cities["n01"] = "深圳"
cities["n02"] = "北京"
cities["n03"] = "上海"
fmt.Println(cities) //map[n01:深圳 n02:北京 n03:上海]

//第三种方式
heroes := map[string]string{
   "hero01": "1",
   "hero02": "2",
   "hero03": "3",
}
heroes["hero04"] = "4"
fmt.Println(heroes) //map[hero01:1 hero02:2 hero03:3]

map 使用的课堂案例

演示一个 key-value 的 value 是 map 的案例

比如:我们要存放 3 个学生信息, 每个学生有 name 和 sex 信息

思路: map[string]map[string]string

studentMap := make(map[string]map[string]string)

studentMap["stu01"] = make(map[string]string, 2)
studentMap["stu01"]["name"] = "tome"
studentMap["stu01"]["age"] = "12"
studentMap["stu01"]["city"] = "shenzhen"

studentMap["stu02"] = make(map[string]string, 2)
studentMap["stu02"]["name"] = "joy"
studentMap["stu02"]["age"] = "11"
studentMap["stu02"]["city"] = "shanghai"

fmt.Println(studentMap)
fmt.Println(studentMap["stu01"])
fmt.Println(studentMap["stu02"])

-----------------------------------------
map[stu01:map[age:12 city:shenzhen name:tome] stu02:map[age:11 city:shanghai name:joy]] 
map[age:12 city:shenzhen name:tome] 
map[age:11 city:shanghai name:joy]

其实就是集合,也就是json

  1. map 的增删改查操作

//第二种方式 常用
cities := make(map[string]string)
cities["n01"] = "深圳"
cities["n02"] = "北京"
cities["n03"] = "上海"
fmt.Println(cities) //map[n01:深圳 n02:北京 n03:上海]

//map["key"] = value key存在就是增加不存在就是修改
cities["n03"] = "重庆"
fmt.Println(cities)

//delete(map,"key")    如果 key 存在,就删除该 key-value,如果 key 不存在,
//不操作,但是也不会报错
delete(cities, "n03")
fmt.Println(cities)

//删除所有map的key,要么遍历key逐个删除,要么map=make()来make新的map
cities = make(map[string]string)

//查找
value, ok := cities["n02"]
if ok {
   fmt.Println("no %v\n", value)
} else {
   fmt.Println("no")
}

  1. map 遍历

一维的map
cities := make(map[string]string)
cities["n01"] = "深圳"
cities["n02"] = "北京"
cities["n03"] = "上海"

for k, v := range cities {
   fmt.Printf("k=%v v=%v\n", k, v)
}
----------------------------------------------
k=n03 v=上海 
k=n01 v=深圳 
k=n02 v=北京
-----------------------------------------------

二位的map,map的值也是map, 先循环取出一个map,再循环取出值
studentMap := make(map[string]map[string]string)

studentMap["stu01"] = make(map[string]string, 2)
studentMap["stu01"]["name"] = "tome"
studentMap["stu01"]["age"] = "12"
studentMap["stu01"]["city"] = "shenzhen"

studentMap["stu02"] = make(map[string]string, 2)
studentMap["stu02"]["name"] = "joy"
studentMap["stu02"]["age"] = "11"
studentMap["stu02"]["city"] = "shanghai"

for k1, v1 := range studentMap {
   fmt.Println("k=", k1)
   for k2, v2 := range v1 {
      fmt.Printf("\t k2=%v v2=%v\n", k2, v2)
   }
   fmt.Println()
}
------------------------------------------------
k= stu02 
         k2=name v2=joy 
         k2=age v2=11 
         k2=city v2=shanghai 

k= stu01 
         k2=age v2=12 
         k2=city v2=shenzhen 
         k2=name v2=tome
------------------------------------------------

  1. map长度

func len
func len(v Type) int
内建函数len返回 v 的长度,这取决于具体类型:
数组:v中元素的数量
数组指针:*v中元素的数量(v为nil时panic)
切片、映射:v中元素的数量;若v为nil,len(v)即为零
字符串:v中字节的数量
通道:通道缓存中队列(未读取)元素的数量;若v为 nil,len(v)即为零

  1. map 切片

切片的数据类型如果是 map,则我们称为 slice of map,map 切片,这样使用则 map 个数就可以动

态变化了

使用一个 map 来记录 monster 的信息 name 和 age, 也就是说一个 monster 对应一个 map,并

且妖怪的个数可以动态的增加=>map 切片

var monsters []map[string]string
monsters = make([]map[string]string, 2)
//增加信息
if monsters[0] == nil {
   monsters[0] = make(map[string]string, 2)
   monsters[0]["name"] = "牛魔王"
   monsters[0]["age"] = "500"
}

if monsters[1] == nil {
   monsters[1] = make(map[string]string)
   monsters[1]["name"] = "猴子"
   monsters[1]["age"] = "5000"
}
//越界 panic: runtime error: index out of range [2] with length 2
//if monsters[2] == nil {
// monsters[2] = make(map[string]string)
// monsters[2]["name"] = "猴子"
// monsters[2]["age"] = "5000"
//}

//针对越界问题,go有append函数动态增加monster
//1. 先定义个monster信息
newMonster := map[string]string{
   "name": "new",
   "age":  "200",
}
monsters = append(monsters, newMonster)
fmt.Println(monsters)

  1. map 排序

  2. golang 中没有一个专门的方法针对 map 的 key 进行排序

  3. golang 中的 map 默认是无序的,注意也不是按照添加的顺序存放的,每次遍历,得到的输出 可能不一样

  4. golang 中 map 的排序,是先将 key 进行排序,然后根据 key 值遍历输出即可

//map排序
map1 := make(map[int]int, 10)
map1[10] = 100
map1[1] = 1
map1[3] = 3
map1[8] = 8
fmt.Println(map1)

//如果安装map的key的顺序仅需排序输出
//1. 先将map的key放入到切片中
//2. 对切片排序
//3. 遍历切片,然后按照key来输出map的值
var keys []int
for k, _ := range map1 {
   keys = append(keys, k)
}
sort.Ints(keys)
fmt.Println(keys)
for _, k := range keys {
   fmt.Printf("map1[%v]=%v\n", k, map1[k])
}
-----------------------------------------
map[1:1 3:3 8:8 10:100] 
[1 3 8 10] 
map1[1]=1 
map1[3]=3 
map1[8]=8 
map1[10]=100
-----------------------------------------

  1. map 使用细节

  2. map 是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改原来 的 map

  3. map 的容量达到后,再想 map 增加元素,会自动扩容,并不会发生 panic,也就是说 map 能动 态的增长 键值对(key-value)

  4. map 的 value 也经常使用 struct 类型,更适合管理复杂的数据(比前面 value 是一个 map 更好) , 比如 value 为 Student 结构体

map 的课堂练习题
  1. 使用 map[string]map[string]sting 的 map 类型
  2. key: 表示用户名,是唯一的,不可以重复
  3. 如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息,(包括昵称 nickname 和 密码 pwd)。
  4. 编写一个函数 modifyUser(users map[string]map[string]sting, name string) 完成上述功能
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值