IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Golang中的map -> 正文阅读

[数据结构与算法]Golang中的map

前言

和大部分编程语言一样,Golang也提供了一种数据类型用来存储键值对(hash)数据,这篇文章我们一起来探讨Golang中map的使用方法以及常见的注意事项

map的底层结构

我们通过以下代码来看下,当我们创建一个map,并往map中添加键值对时,底层都做了些啥

func main() {
	// 声明一个map m1
	m1 := make(map[string]int)
	// 添加键值对 a:1
	m1["a"] =1
}

在这里插入图片描述
map会初始时,内部有一个hash表,该表中有一定数量的hash桶。当我们往hash表中添加键值对时,map会先用hash函数计算key的hash值,然后根据hash值定位到具体的hash桶。
map中的查找逻辑也是类似的

map中的键

不能做key的数据类型

我们通过Go语言规范中可以知道,map中的key必须是可以进行判等的(== 或 !=),而「函数类型」、「字典类型」、「切片类型」在Golang设计之初就是不支持判等的(我猜是因为这三者都属于引用类型,对指针指向的元数据是否相等不太好判定)。所以map中的键不能是「函数类型」、「字典类型」、「切片类型」

a1 := []int{1, 2}
a2 := a1
// 这行代码会出现编译错误
// Invalid operation: a1 == a2 (the operator == is not defined on []int)
fmt.Println(a1 == a2)

最好不要做key的数据类型

Golang中是可以用interface作为key的,但是一般不建议这么玩!究其原因我们会在接下来的文章中详细分析

func main() {
	m1 := map[interface{}]string{
		"a":           "aa",
		[]string{"1"}: "bb", // 这行代码会触发panic runtime error: hash of unhashable type []string
	}
	fmt.Println(m1)
}

我们声明并初始化key为interface类型的map(可以正常编译通过),当key的动态类型为值类型是没有问题的。但是当key的动态类型为不可比较的类型时(比如切片),此时程序运行时会panic。所以Go规范中一般不建议将key设置为interface类型,因为会躲过程序的编译器检查,导致程序不可控。

为什么不能将不可比较的类型当做key

文章的开始我们已经描述了map的底层结构,当我们进行hash查找时,首先会用hash函数计算key的哈希值,根据hash值找到对应的bucket。最后再拿原始key值和bucket中的key值进行比较。这里有人就会问了,直接比较hash值不就可以了么,为什么还需要比较原始key值?

因为不同key值可能会产生相同的hash值(哈希冲突),所以只有当hash值相同并且原始key相同才证明是我们要查找的元素。讲到这里我想你应该明白为什么Golang中要求key的类型要求为可比较类型了吧

不要对值为nil的map进行添加键值对操作

func main() {
	var m1 map[int]string
	// 这行代码会触发panic
	// m1[1] = "aa"
	fmt.Println(m1[2])
	delete(m1, 2)
}

如上代码所示,我们不要对值为nil的map进行添加/修改键值对操作,这里会造成 panic: assignment to entry in nil map,如果你有用编辑器的话(例如Goland),编辑器会给出对应的告警。但是我们对值为nil的map进行查询和删除时,程序是能够正常运行的。不过我还是建议你使用make来声明map

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:56:50  更:2022-04-07 22:58:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:40:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码