【Golang第7章:map】go语言中map的基本介绍,golang中map的使用案例,go语言中map的增删改查操作,go语言对map的值进行排序

介绍

这个是在B站上看边看视频边做的笔记,这一章是编程语言go语言的map部分

有go语言中map的基本介绍,golang中map的使用案例,go语言中map的增删改查操作,go语言对map的值进行排序,具体请看【文章目录】

配套视频自己去B站里面搜【go语言】,最高的播放量就是

里面的注释我写的可能不太对,欢迎大佬们指出╰(°▽°)╯

(七)、map

一、map 的基本介绍

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



二、map 的声明

1.基本语法

var map 变量名map[keytype]valuetype

  • key 可以是什么类型

    golang 中的map,的key 可以是很多种类型,比如bool, 数字,string, 指针, channel , 还可以是只包含前面几个类型的接口, 结构体, 数组

    key 通常为intstring

    注意: slice, map 还有function 不可以,因为这几个没法用== 来判断

  • valuetype 可以是什么类型

    valuetype 的类型和key 基本一样

    通常为: 数字(整数,浮点数),string,map,struct



2.map 声明的举例

  • map 声明的举例:

    var a map[string]string

    var a map[string]int

    var a map[int]string

    var a map[string]map[string]string

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

  • 案例演示:

    func main() {
    	//map的声明和注意事项
    	var a map[string]string
    	/*
    		a["no1"] = "宋江"   //由于只声明了一个空map,没有给予他一个空间,所以出现报错给一个空map赋值报错
    		fmt.Println(a)
    	*/
    
    	//在使用map前,需要先make,make的作用是给map分配数据空间
    	a = make(map[string]string, 10)
    	a["no1"] = "宋江"
    	a["no2"] = "吴用"
    	a["no1"] = "武松"
    	a["no3"] = "吴用"
    	fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用]
    }
    
  • 对上面代码说明:

    1. map 在使用前一定要make
    2. map 的key 是不能重复,如果重复了,则以最后这个key-value 为准
    3. map 的value 是可以相同的.
    4. map 的key-value 是无序
    5. make 内置函数数目

在这里插入图片描述



3.map 的使用

func main() {
	//方式1
	var a = make(map[string]string, 10)
	a["no1"] = "宋江"
	a["no2"] = "吴用"
	a["no1"] = "武松"
	a["no3"] = "吴用"
	fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用]

	//方式2
	ctiies := make(map[string]string)
	ctiies["no1"] = "北京"
	ctiies["no2"] = "上海"
	ctiies["no3"] = "广州"
	fmt.Println(ctiies)

	//方式3
	heroes := map[string]string{"hero1": "宋江", "hero2": "武松"}
	heroes["hero3"] = "林冲"
	fmt.Println(heroes)
}
  • map使用案例

    练习:演示一个key-valuevaluemap 的案例

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

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

    代码:

    	//案例
    	/*
    		演示一个key-value 的value 是map 的案例
    		比如:我们要存放3 个学生信息, 每个学生有name 和sex 信息
    		思路: map[string]map[string]string
    	*/
    	studentMap := make(map[string]map[string]string) //map嵌套,make第一个map
    
    	studentMap["stu01"] = make(map[string]string) //make第二个map
    	studentMap["stu01"]["name"] = "Tom"           //嵌套赋值
    	studentMap["stu01"]["sex"] = "男"
    	studentMap["stu01"]["address"] = "北京"
    
    	studentMap["stu02"] = make(map[string]string) //make第二个map
    	studentMap["stu02"]["name"] = "Mary"
    	studentMap["stu02"]["sex"] = "女"
    	studentMap["stu02"]["address"] = "上海"
    
    	fmt.Println(studentMap)                  //查看整个map值
    	fmt.Println(studentMap["stu02"])         //查看map指定的key
    	fmt.Println(studentMap["stu02"]["name"]) //查看嵌套map内指定的值
    


4.map的增删改查操作

  • map 增加和更新:

    map["key"] = value //如果key 还没有,就是增加,如果key 存在就是修改

    	ctiies := make(map[string]string)
    	ctiies["no1"] = "北京"
    	ctiies["no2"] = "上海"
    	ctiies["no3"] = "广州"
    	fmt.Println(ctiies)
    
    	//因为no3这个key已经存在,因此下面的这句话就是修改
    	ctiies["no3"] = "上海~"
    	fmt.Println(ctiies)
    


  • map 查找:

    案例演示:

    	//演示map的查找
    	val, ok := ctiies["no1"]
    	if ok {
    		fmt.Printf("有no1 key ,值为%v\n", val)
    	} else {
    		fmt.Println("没有no1 key")
    	}
    

    对上面代码的说明:

    说明:如果heroes 这个map 中存在"no1" , 那么findRes 就会返回true,否则返回false



  • map 删除:

    说明:

    delete(map,"key")delete 是一个内置函数,如果key 存在,就删除该key-value,如果key 不存在,不操作,但是也不会报错

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qlkh2K04-1669361145534)(assets/image-20221013142404245.png)]

    代码:

    	//演示删除
    	delete(ctiies, "no1")
    	fmt.Println(ctiies)
    
    	delete(ctiies, "no4")
    	fmt.Println(ctiies)
    


  • 细节说明:

    1.如果我们要删除map 的所有key ,没有一个专门的方法一次删除,可以遍历一下key, 逐个删除

    2.或者map = make(...),make 一个新的,让原来的成为垃圾,被gc 回收

    代码:

    	//如果希望一次性删除所有的key
    	//1.遍历所有的key,如何逐一删除 [遍历]
    	//2.直接make-个新的空间
    	cities := make(map[string]string)
    	fmt.Println(cities) //map[]
    


5.map 遍历和长度

案例演示相对复杂的map 遍历:该map 的value 又是一个map

说明:map 的遍历使用for-range 的结构遍历

  • 案例演示:

    func main() {
    	//使用for-range遍历map
    	ctiies := make(map[string]string)
    	ctiies["no1"] = "北京"
    	ctiies["no2"] = "上海"
    	ctiies["no3"] = "广州"
    
    	for k, v := range ctiies {
    		fmt.Printf("k=%v v=%v\n", k, v)
    	}
    
    	//使用for -range遍历一个结构比较复杂的map
    	studentMap := make(map[string]map[string]string) //map嵌套,make第一个map
    
    	studentMap["stu01"] = make(map[string]string) //make第二个map
    	studentMap["stu01"]["name"] = "Tom"           //嵌套赋值
    	studentMap["stu01"]["sex"] = "男"
    	studentMap["stu01"]["address"] = "北京"
    
    	studentMap["stu02"] = make(map[string]string) //make第二个map
    	studentMap["stu02"]["name"] = "Mary"
    	studentMap["stu02"]["sex"] = "女"
    	studentMap["stu02"]["address"] = "上海"
    
    	for k1, v1 := range studentMap { //先获取第一个map的key
    		fmt.Printf("k1=%v\n", k1)
    		for k2, v2 := range v1 { //使用第一个map的key进行循环,获取第二个map的key
    			fmt.Printf("\tk2=%v v2=%v\n", k2, v2)
    		}
    	}
    }
    


  • map的长度

在这里插入图片描述



6.map 切片

1)基本介绍

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

态变化了。



2)案例演示

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

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

func main() {
	//演示map切片的使用
	/*
	 要求:使用一个map 来记录monster 的信息name 和age, 也就是说一个monster 对应一个map,并

	 且妖怪的个数可以动态的增加=>map 切片
	*/
	var monsters []map[string]string        //声明一个map切片
	monsters = make([]map[string]string, 2) //对map进行make,生成2个map空间
	if monsters[0] == nil {
		monsters[0] = make(map[string]string, 2) //对第1个map空间的第进行初始化,能放2个值
		monsters[0]["name"] = "牛魔王"
		monsters[0]["age"] = "500"
	}

	if monsters[1] == nil {
		monsters[1] = make(map[string]string, 2) //对第2个map空间的第进行初始化,能放2个值
		monsters[1]["name"] = "红孩儿"
		monsters[1]["age"] = "400"
	}
	fmt.Println(monsters) //[map[age:500 name:牛魔王] map[age:400 name:红孩儿]]

	//这里我们需要使用到切片的append函数,可以动态的增加monster
	//1.先定义个monster信息
	newMonster := map[string]string{"name": "哥布林", "age": "50"}                //直接定义一个map并赋值
	newMonster1 := map[string]string{"name": "黑龙", "age": "200", "sex": "123"} //直接定义一个map并赋值
	monsters = append(monsters, newMonster, newMonster1)                       //内建函数append将元素追加到切片的末尾

	fmt.Println(monsters) //[map[age:500 name:牛魔王] map[age:400 name:红孩儿] map[age:50 name:哥布林] map[age:200 name:黑龙 sex:123]]
}


7.map 排序

1)基本介绍

  1. golang 中没有一个专门的方法针对map 的key 进行排序
  2. golang 中的map 默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样. 【案例演示1】
  3. golang 中map 的排序,是先将key 进行排序,然后根据key 值遍历输出即可


2)演示案例

package main

import (
	"fmt"
	"sort"
)

func main() {
	//map的排序
	map1 := make(map[int]int)
	map1[10] = 100
	map1[1] = 13
	map1[4] = 56
	map1[8] = 90

	fmt.Println(map1)

	for k, v := range map1 { //查看是否是无序的
		fmt.Printf("key:%v\tvalue:%v\n", k, v) //每次输出的顺序不一样
	}

	//如果按照map的key的顺序进行排序输出
	//1.先将map的key 放入到切片中
	//2.对切片排序
	//3.遍历切片,然后按照key来输出map的值
	var keys []int
	for k, _ := range map1 {
		keys = append(keys, k) //使用append递增获取所有的key
	}

	//对key进行排序
	fmt.Println(keys)
	sort.Ints(keys) //将值按递增的顺序排列
	fmt.Println(keys)

	for _, k := range keys { //按排列好的大小来获取去map1的值
		fmt.Printf("map1[%v]=%v\n", k, map1[k])
	}
}


8.map 使用细节

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

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

    package main
    
    import "fmt"
    
    func modify(map1 map[int]int) {
    	map1[10] = 900
    }
    
    func main() {
    	//map是引用类型,遵守引用类型传递的机制,在一个函数接收map,
    	//修改后,会直接修改原来的map
    	map1 := make(map[int]int, 2) //默认给的容量是2 ,但是没有报错,而且申明的4个都输出了
    	map1[1] = 90
    	map1[2] = 88
    	map1[10] = 1
    	map1[20] = 2
    	fmt.Println(map1) //map[1:90 2:88 10:1 20:2]
    	modify(map1)
    	fmt.Println(map1) //map[1:90 2:88 10:900 20:2] 说明map是引用类型
    
    }
    
  • map 的value 也经常使用struct 类型,更适合管理复杂的数据(比前面value 是一个map 更好),比如value为Student 结构体【案例演示,因为还没有学结构体,体验一下即可】

    package main
    
    import "fmt"
    
    //声明一个学生的结构体
    type Stu struct {
    	Name    string
    	Age     int
    	Address string
    }
    
    func main() {
    	//map的value也经常使用struct类型,
    	//更适合管理复杂的数据(比前面value是一一 个map更好),
    	//比如value为student结构体[ 案例演示,因为还没有学结构体,体验一下即可]
    	//1.map 的key 为学生的学号,是唯一的
    	//2.map的value为结构体,包含学生的名字,年龄,地址
    
    	students := make(map[string]Stu, 10) //make分配空间并设定类型
    	//创建2个学生
    	stu1 := Stu{"tom", 18, "北京"}  //学生1的信息
    	stu2 := Stu{"mary", 28, "上海"} //学生2的信息
    	students["no1"] = stu1
    	students["no2"] = stu2
    
    	fmt.Println(students)
    
    	//遍历各个学生的信息
    	for k, v := range students { //获取key值和结构体
    		fmt.Printf("学生的编号是%v", k)
    		fmt.Printf("学生的名字是%v", v.Name) //获取结构体的值
    		fmt.Printf("学生的年龄是%v", v.Age)
    		fmt.Printf("学生的地址是%v", v.Address)
    		fmt.Println()
    	}
    }
    


9.map 的练习题

  • 课堂练习:

    1. 使用map[string]map[string]string 的map 类型
    2. key: 表示用户名,是唯一的,不可以重复
    3. 如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息,(包括昵称nickname 和密码pwd)。
    4. 编写一个函数modifyUser(users map[string]map[string]string, name string) 完成上述功能
  • 代码

    package main
    
    import "fmt"
    
    //1) 使用map[string]map[string]string 的map 类型
    //2) key: 表示用户名,是唯一的,不可以重复
    //3) 如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息,(包括昵称nickname 和密码pwd)。
    //4) 编写一个函数modifyUser(users map[string]map[string]string, name string) 完成上述功能
    
    func modifyUser(users map[string]map[string]string, name string) { //声明users的map和声明name的类型
    	//判断users中是否有这个name
    	if users[name] != nil { //有这个用户
    		users[name]["passwd"] = "888888" //修改这个用户的密码为888888
    
    	} else { //没有这个用户
    		users[name] = make(map[string]string, 2) //make 一个空间,声明vlue的空间和默认参数
    		users[name]["passwd"] = "888888"
    		users[name]["nickname"] = "昵称" + name
    	}
    }
    
    func main() {
    	users := make(map[string]map[string]string, 10)
    	users["smith"] = make(map[string]string, 2) //声明Smith密码和昵称
    	users["smith"]["passwd"] = "999999"
    	users["smith"]["nickname"] = "我是史密斯"
    	fmt.Println(users)
    
    	modifyUser(users, "tom") //传入参数,没有的名称就添加,有的就修改密码
    	modifyUser(users, "mary")
    	modifyUser(users, "smith")
    
    	fmt.Println(users)
    }
    

章节目录

【Golang第1~3章:基础】如何安装golang、第一个GO程序、golang的基础

【Golang第4章:函数】Golang包的引用,return语句、指针、匿名函数、闭包、go函数参数传递方式,golang获取当前时间

【Golang第5章:数组与切片】golang如何使用数组、数组的遍历和、使用细节和内存中的布局;golang如何使用切片,切片在内存中的布局

【Golang第6章:排序和查找】golang怎么排序,golang的顺序查找和二分查找,go语言中顺序查找二分查找介绍和案例

【Golang第7章:map】go语言中map的基本介绍,golang中map的使用案例,go语言中map的增删改查操作,go语言对map的值进行排序

【Golang第8章:面向对象编程】Go语言的结构体是什么,怎么声明;Golang方法的调用和声明;go语言面向对象实例,go语言工厂模式;golang面向对象的三大特性:继承、封装、多态

【Golang第9章:项目练习】go项目练习家庭收支记账软件项目、go项目练习客户管理系统项目

【Golang第10章:文件操作】GO语言的文件管理,go语言读文件和写文件、GO语言拷贝文件、GO语言判断文件是否存在、GO语言Json文件格式和解析

【Golang第11章:单元测试】GO语言单元测试

【Golang第12章:goroutine协程与channel管道】GO语言goroutine协程和channel管道的基本介绍、goroutine协

posted @ 2022-11-25 15:32  雪花凌落的盛夏  阅读(38)  评论(0编辑  收藏  举报  来源