卷毛0基础学习Golang-基础-map字典

卷毛0基础学习Golang-基础-map字典

持续更新中-----欢迎收藏

Go语言中的map(映射、字典)是一种内置的数据结构,它是一个无序的key-value对的集合,比如以身份证号作为唯一键来标识一个人的信息。Go语言中并没有提供一个set类型,但是map中的key也是不相同的,可以用map实现类似set的功能。

在这里插入图片描述
map格式为:

   map[keyType]valueType

在一个map里所有的键都是唯一的,而且必须是支持==和!=操作符的类型,切片、函数以及包含切片的结构类型这些类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误:

 dict := map[ []string ]int{} //err, invalid map key type []string

map值可以是任意类型,没有限制。map里所有键的数据类型必须是相同的,值也必须如此,但键和值的数据类型可以不相同。

注意:map是无序的,我们无法决定它的返回顺序,所以,每次打印结果的顺利有可能不同。

创建、初始化map

创建map
	var m1 map[int]string   //只是声明一个map,没有初始化, 为空(nil)map
	fmt.Println(m1 == nil) 	//true
	//m1[1] = "Luffy" 		//nil的map不能使用err, panic: assignment to entry in nil map
	
	m2 := map[int]string{}	//m2, m3的创建方法是等价的
	m3 := make(map[int]string)
	fmt.Println(m2, m3) 		//map[] map[]
	m4 := make(map[int]string, 10) 	//第2个参数指定容量
	fmt.Println(m4)                	//map[]

创建m4的方法指定了map的初始创建容量。 与slice类似,后期在使用过程中,map可以自动扩容。只不过map更方便一些,不用借助类似append的函数,直接赋值即可。如,m1[17] = “Nami”。赋值过程中,key如果与已有map中key重复,会将原有map中key对应的value覆盖。

但是!对于map而言,可以使用len()函数,但不能使用cap()函数。

初始化map
也可以直接指定初值,要保证key不重复。
	//1、定义同时初始化
	var m1 map[int]string = map[int]string{1: "Luffy", 2: "Sanji"}
	fmt.Println(m1) //map[1:Luffy 2:Sanji]
	
	//2、自动推导类型 :=
	m2 := map[int]string{1: "Luffy", 2: "Sanji"}
	fmt.Println(m2)
常用操作
赋值
	m1 := map[int]string{1: "Luffy", 2: "Sanji"}
	m1[1] = "Nami"   //修改
	m1[3] = "Zoro"  //追加, go底层会自动为map分配空间
	fmt.Println(m1) //map[1:Nami 2:Sanji 3:Zoro]
	
	m2 := make(map[int]string, 10) 	//创建map
	m2[0] = "aaa"
	m2[1] = "bbb"
	fmt.Println(m2)           		//map[0:aaa 1:bbb]
	fmt.Println(m2[0], m2[1]) 		//aaa bbb
遍历

Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。在实践中,遍历的顺序是随机的,每一次遍历的顺序都不相同。这是故意的,每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。

	m1 := map[int]string{1: "Luffy", 2: "Sanji"}
	//遍历1,第一个返回值是key,第二个返回值是value
	for k, v := range m1 {
	    fmt.Printf("%d ----> %s\n", k, v)
	    //1 ----> Luffy
	    //2 ----> yoyo
	}
	
	//遍历2,第一个返回值是key,第二个返回值是value(可省略)
	for k := range m1 {
	    fmt.Printf("%d ----> %s\n", k, m1[k])
	    //1 ----> Luffy
	    //2 ----> Sanji
	}

有时候可能需要知道对应的元素是否真的是在map之中。可以使用下标语法判断某个key是否存在。map的下标语法将产生两个值,其中第二个是一个布尔值,用于报告元素是否真的存在。
如果key存在,第一个返回值返回value的值。第二个返回值为 true。

	value, ok := m1[1]
	fmt.Println("value = ", value, ", ok = ", ok) //value =  mike , ok =  true

如果key不存在,第一个返回值为空,第二个返回值为false。

	value2, has := m1[3]
	fmt.Println("value2 = ", value2, ", has = ", has) //value2 =   , has =  false
删除

使用delete()函数,指定key值可以方便的删除map中的k-v映射。

	m1 := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"}
	
	for k, v := range m1 {	//遍历,第一个返回值是key,第二个返回值是value
		fmt.Printf("%d ----> %s\n", k, v)
	}
	//1 ----> Sanji
	//2 ----> Sanji
	//3 ----> Zoro
	delete(m1, 2) 		//删除key值为2的map
	
	for k, v := range m1 {
		fmt.Printf("%d ----> %s\n", k, v)
	}
	//1 ----> Luffy
	//3 ----> Zoro
	delete(m1, 5) 		//删除key值为5的map
	
	for k, v := range m1 {
	    fmt.Printf("%d ----> %s\n", k, v)
	}
	//1 ----> Luffy
	//3 ----> Zoro

delete()操作是安全的,即使元素不在map中也没有关系;如果查找删除失败将返回value类型对应的零值。

map输出结果依然是原来的样子,且不会有任何错误提示。

map做函数参数

与slice 相似,在函数间传递映射并不会制造出该映射的一个副本,不是值传递,而是引用传递:

	func DeleteMap(m map[int]string, key int) {
	delete(m, key) //删除key值为2的map
	for k, v := range m {
	    fmt.Printf("len(m)=%d, %d ----> %s\n", len(m), k, v)
	}
	//len(m)=2, 1 ----> Luffy
	//len(m)=2, 3 ----> Zoro
	}
	
	func main() {
	m := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"}
	DeleteMap(m, 2) 	//删除key值为2的map
	
	for k, v := range m {
	    fmt.Printf("len(m)=%d, %d ----> %s\n", len(m), k, v)
	}
	//len(m)=2, 1 ----> Luffy
	//len(m)=2, 3 ----> Zoro
	}
map做函数返回值

返回的依然是引用

	func test() map[int]string {
		// m1 := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"}
		m1 := make(map[int]string, 1)     // 创建一个初创容量为1的map
		m1[1] = "Luffy"
		m1[2] = "Sanji"                   // 自动扩容
		m1[67] = "Zoro"
		m1[2] = "Nami"                	// 覆盖 key值为2 的map
		fmt.Println("m1 = ", m1)
		return m1
	}
	
	func main() {
		m2 := test()                  	// 返回值 —— 传引用
		fmt.Println("m2 = ", m2)
	}

输出:
m1 = map[1:Luffy 2:Nami 67:Zoro]
m2 = map[2:Nami 67:Zoro 1:Luffy]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值