吃透 Golang 基础:数据结构之 Map
文章目录
- Map
- 概述
- 初始化
- 删除
- 访问不存在的 key 返回 value 的零值
- 遍历 map
- map 自身的零值
- map 索引时返回的第二个参数
- 使用 map 实现 set
Map
Hash Map 是无序的 key/value 对集合,其中所有的 key 都是不同的。通过给定的 key 可以在常数时间复杂度内完成检索、更新或删除对应的 value(基于 Hash Map 的增删改查操作时间复杂度为$ O(1) $)
概述
Go 中的 map 就是一个 Hash Map 的引用,map 类型可以写为 map[K]V
,其中K
和V
分别对应 key 和 value。map 中所以 key 可以是相同类型,所以 value 可以是相同类型,但 key 和 value 的类型可以不同。需要注意的是,K
对应的 key 必须支持==
比较运算符,这样 map 就可以通过测试 key 是否相等来判断传入的 key 是否已经存在。另一个要注意的点是最好不要使用浮点数作为 key,因为浮点数的比较是不准确的。value 的类型没有任何限制。
初始化
可以使用内置的 make 函数创建一个 map(make 只能用于创建 slice/map/channel):
ages := make(map[string]int)
也可以使用字面值语法来创建一个新的 map,同时可以指定初始的 key/value:
ages := map[string]int{"yggp": 24,"ed": 24,
}// 上述方式等价于
ages := map[string]int{}
ages["yggp"] = 24
ages["ed"] = 24fmt.Println(ages["yggp"]) // 访问 map 当中的元素时可以通过 key 对应的下标来访问
删除
可以使用内置的 delete 函数删除元素:
delete(ages, "ed") // remove element ages["ed"]
通过内置的 delete,将会直接删除 ages 这个 map 当中的 key/value。在 LeetCode 的 LRU Cache 这道题当中就会用到 delete 来删除 Cache 当中最近最久未使用的 key/value。
访问不存在的 key 返回 value 的零值
上述所有的增/删/改/查操作都是安全的,即使这些元素不在操作的 map 当中。如果一个 key 的查找失败了,那么将直接返回 value 对应的零值,比如ages["kevin"]
的查找结果将直接返回 int 类型的零值0
。对于ages["kevin"] = ages["kevin"] + 1
这样的语句也是可以正常执行的,该语句自右向左执行,最终ages["kevin"]
的值为 1。+=
和++
也可以用于 value 为整型的 map 上。
需要注意的是,map 中的元素不是一个变量,因此我们不能对 map 的元素进行取址操作:
// ❌非法的取址操作, compile error
_ = &ages["ed"]
禁止对 map 取址的原因是 map 可能随着元素数量的增长而重新分配更大的内存空间,从而导致之前的地址失效。
遍历 map
可以通过 range 风格的 for 循环来遍历 map 中的 key/value pair:
for key, value := range ages {fmt.Printf("%s\t%d\n", key, value)
}
map 的迭代顺序是不确定的,在实践中,遍历的顺序是随机的,也就是每一次遍历的顺序都不相同。因此,Go 的 map 是无序的,如果想要有序,可以首先取出所有的 key 到 slice 当中,然后再对 slice 进行排序,用 slice 当中排序后的结果索引 map 当中的 value。
map 自身的零值
map 类型的零值是 nil,也就是没有任何引用的 Hash Map。
var ages map[string]int
fmt.Println(ages == nil) // true
fmt.Println(len(ages) == 0) // true, 意味着 nil 的 map 长度为 0
map 上的大部分操作,包括查找、删除、len 和 range 循环都可以安全工作在 nil 的 map 上,但是试图向 nil 的 map 增加值会导致 panic。也就是说,向 map 当中存数据之前必须先创建好 map。
map 索引时返回的第二个参数
我们已经知道,通过 key 作为索引下标来访问 map 会产生一个 value。无论 key/value pair 之前是否已经记录在了 map 当中,都会产生相应的结果:如果 key 存在,则返回对应的 value 值,否则返回 value 类型的零值。有些情况下我们想要确切地知道 key/value 是否存在于 map 当中,这个时候就可以用到 map 索引返回的第二个参数:
age, ok := ages["bob"]
if !ok {// ... ... ...
}
上面代码块的ok
就是第二个参数,它是一个 bool 值,代表 key 对应的 value 是否存在于 map 当中。
和 slice 一样,map 与 map 之间是不可比较的,map 本身只能和 nil 进行比较,来判断 map 是否引用了 Hash Map。如果想要比较两个类型相同的 map,唯一的方法就是逐 key/value 进行比较。
使用 map 实现 set
Go 当中没有 set 类型,但是我们可以通过 map 来模拟一个 set 类型。一种常见的 set 声明方法是:
// ... ... ...
st := make(map[string]bool)
// ... ... ...
可以使用忽略 value 的 map 作为一个 string 类型的 set,关键在于通过 map 查找返回的第二个参数 ok 来判断当前 key 是否已经存在于 map 当中,这恰好模拟了 set 的效果。
最开始的时候我们已经提到 map 的 value 类型可以是任何类型,比如 map 或 slice。下面的例子来自于《Go 语言圣经》,graph 是一个 map,它的 key 是 string,value 类型是 map[string]bool
,代表一个字符串集合。具体来说,graph 将 string 类型的 key 映射到一组相关的 string set:
var graph = make(map[string]map[string]bool)func addEdge(from, to string) {edges := graph[from]if edges == nil {edges = make(map[string]bool)graph[from] = edges}edges[to] = true
}func hasEdge(from, to string) bool {return graph[from][to]
}
addEdge
惰性初始化 map,也就是每个值首次作为 key 时才初始化。hasEdge 显示了如何让 map 的零值也能正常工作:即使 from 到 to 的边不存在,graph[from][to]
仍然可以返回 bool 的零值 false 作为有意义的结果。
相关文章:

吃透 Golang 基础:数据结构之 Map
文章目录 Map概述初始化删除访问不存在的 key 返回 value 的零值遍历 mapmap 自身的零值map 索引时返回的第二个参数使用 map 实现 set Map Hash Map 是无序的 key/value 对集合,其中所有的 key 都是不同的。通过给定的 key 可以在常数时间复杂度内完成检索、更新或…...
ABP VNext 与 Neo4j:构建基于图数据库的高效关系查询
ABP VNext 与 Neo4j:构建基于图数据库的高效关系查询 🚀 在社交网络、权限图谱、推荐系统等应用场景中,关系链深度和复杂度远超传统关系型数据库的表达能力。本文基于 ABP VNext 框架,集成 Neo4j 图数据库,构建一套高…...
数论——同余问题全家桶3 __int128和同余方程组
数论——同余问题全家桶3 __int128和同余方程组 快速读写和__int128快速读写__int128 中国剩余定理和线性同余方程组中国剩余定理(CRT)中国剩余定理OJ示例模板题曹冲养猪 - 洛谷模板题猜数字 - 洛谷 扩展中国剩余定理扩展中国剩余定理OJ示例模板题扩展中国剩余定理(…...
leetcode47.全排列II:HashSet层去重与used数组枝去重的双重保障
一、题目深度解析与重复排列问题 题目描述 给定一个可能包含重复数字的数组nums,返回其所有不重复的全排列。解集不能包含重复的排列,且排列可以按任意顺序返回。例如: 输入:nums [1,1,2]输出:[[1,1,2],[1,2,1],[2…...

5.Nginx+Tomcat负载均衡群集
Tomcat服务器应用场景:tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。一般来说,Tomcat虽然和Apache或…...

React项目的状态管理:Redux Toolkit
目录 1、搭建环境 2、Redux Toolkit 包含了什么 3、使用示例 (1)创建user切片 (2)合并切片得到store (3)配置store和使用store 使用js来编写代码,方便理解一些 1、搭建环境 首先…...

跨界破局者鲁力:用思辨与创新重塑汽车流通行业标杆
来源:投资家 在汽车流通行业深度变革的浪潮中,东莞东风南方汽车销售服务有限公司塘厦分公司总经理鲁力历经近二十年行业深耕,构建了一条从汽车销售顾问到区域运营掌舵者的进阶范本。作为东风日产体系内兼具理论建构与实战穿透力的标杆管理者…...
Druid连接池实现自定义数据库密码加解密功能详解
Druid连接池实现自定义数据库密码加解密功能详解 在企业级应用开发中,数据库密码的明文存储是一个显著的安全隐患。Druid作为阿里巴巴开源的高性能数据库连接池组件,提供了灵活的密码加密与解密功能,允许开发者通过自定义逻辑实现数据库密码…...

OS11.【Linux】vim文本编辑器
目录 1.四种模式 命令模式 几个命令 插入模式 底行模式 一图展示三种模式之间的关系 2.分屏(多文件操作) 3.配置vim的原理 4.脚本一键配置vim CentOS 7 x86_64 其他发行版 5.NeoVim(推荐) vim文本编辑器是一个多模式的编辑器,因此先介绍它的四种模式 附vim的官网:…...

基于SFC的windows系统损坏修复程序
前言 在平时使用Windows操作系统时会遇到很多因为系统文件损坏而出现的错误 例如:系统应用无法打开 系统窗口(例如开始菜单)无法使用 电脑蓝屏或者卡死 是如果想要修复很多人只能想到重装系统。但其实Windows有一个内置的系统文件检查器可以修复此类错误。 原理 SFC命令…...
强化学习基础概念图文版笔记
📘 强化学习基础概念图文版笔记 1️⃣ 基本框架:Agent 与 Environment 🧠 核心角色: Agent(智能体):做出决策的“大脑”,根据当前状态选择动作。Environment(环境&…...
k8s下离线搭建elasticsearch
前提 已经完成k8s安装 已经完成相关组件如helm的安装 下载es的chart包 如下地址 https://helm.elastic.co/helm/elasticsearch/elasticsearch-版本号.tgz 如6.8.10 https://helm.elastic.co/helm/elasticsearch/elasticsearch-6.8.10.tgz 修改配置 修改value.yaml文件…...

WAF绕过,网络层面后门分析,Windows/linux/数据库提权实验
一、WAF绕过文件上传漏洞 win7:10.0.0.168 思路:要想要绕过WAF,第一步是要根据上传的内容找出来被拦截的原因。对于文件上传有三个可以考虑的点:文件后缀名,文件内容,文件类型。 第二步是根据找出来的拦截原…...
Oracle杀进程注意事项
文章目录 一、哪些后台进程杀死会导致数据库重启二、杀死哪些后台进程会导致数据库关闭三、杀死哪些后台进程对数据库没有影响 一、哪些后台进程杀死会导致数据库重启 CKPT:检查点进程,checkpoint 检查点,检查点事件的责任是:标志…...

Vue 3 弹出式计算器组件(源码 + 教程)
🧮 Vue 3 弹出式计算器组件(源码 教程) 📌 建议收藏 点赞 关注,本组件支持加减乘除、双向绑定、计算过程展示,适用于表单辅助输入场景。 🔧 一、完整源码(复制即用) …...

监测预警系统重塑隧道安全新范式
在崇山峻岭的脉络间延伸的隧道,曾是交通安全的薄弱环节。智慧隧道监测预警系统的诞生,正在彻底改变这种被动防御格局,通过数字神经网络的构建,为地下交通动脉注入智能守护基因。 一、安全防控体系的质变升级 1.风险感知维度革命…...
solidity中sar和>>的区别
sar和>>都是右移操作,其区别简而言之前者保留符号位,后者不保留。要解释清楚这个问题,需要从有符号数和无符号数讲起: 有符号数和无符号数 打个比方int8和uint8 uint8(无符号 8 位整数) 取值范围:…...
ESP32与STM32
ESP32与STM32深度对比:物联网与嵌入式开发的王者之争 一、核心架构对比 1.1 ESP32 - 无线物联网霸主 // 典型双核架构配置 #include "freertos/FreeRTOS.h" #include "freertos/task.h"void app_main() {// 核心0执行无线通信任务xTaskCreat…...
vue在打包的时候能不能固定assets里的js和css文件名称
在 Vue 项目中(特别是使用 Vue CLI 构建的项目),打包时生成的 assets 目录下的 .js 和 .css 文件默认会带有哈希值(如 app.123abc.js),这是为了缓存优化。但你可以配置固定名称,方法如下&#x…...
用设计模式重新思考(类FSM)验证:从混乱到优雅
在数字设计的世界里,Finite-State Machine(FSM)就像一个城市的交通信号系统。每个状态都有自己的规则,每个转换都需要精确的条件。而对于验证工程师来说,如何优雅地验证这些状态机,一直是个让人头疼的问题。…...

技巧小结:外部总线访问FPGA寄存器
概述 需求:stm32的fsmc总线挂载fpga,stm32需要访问fpga内部寄存器 1、分散加载文件将变量存放到指定地址即FPGA寄存器地址 sct文件指定变量存储地址,从而可以直接访问外设,(28335也可以,不过用的是cmd文件…...
Qt客户端技巧 -- 窗口美化 -- 圆角窗口
不解析,直接给代码例子 利用窗口重绘事件处理函数paintEvent main.cpp #include <QtCore/qglobal.h> #if QT_VERSION > 0x050000 #include <QtWidgets/QApplication> #else #include <QtGui/QApplication> #endif#include "roundedwin…...
Go语言爬虫系列教程5:HTML解析技术以及第三方库选择
Go语言爬虫系列教程5:HTML解析技术以及第三方库选择 在上一章中,我们使用正则表达式提取网页内容,但这种方法有局限性。对于复杂的HTML结构,我们需要使用专门的HTML解析库。在这一章中,我们将介绍HTML解析技术以及如何…...
理解JavaScript中map和parseInt的陷阱:一个常见的面试题解析
前言 在JavaScript面试中,map和parseInt的组合常常被用作考察候选人对这两个方法理解深度的题目。让我们通过一个简单的例子来深入探讨其中的原理。 问题现象 [1, 2, 3].map(parseInt) // 输出结果是什么?很多人可能会预期输出[1, 2, 3],但…...
文件上传漏洞深度解析:检测与绕过技术矩阵
文件上传漏洞深度解析:检测与绕过技术矩阵 引言:无处不在的文件上传风险 在当今的Web应用生态系统中,文件上传功能几乎无处不在。从社交媒体分享图片到企业文档管理系统,用户上传文件已成为现代Web应用的核心功能之一。然而&…...
3.2 HarmonyOS NEXT跨设备任务调度与协同实战:算力分配、音视频协同与智能家居联动
HarmonyOS NEXT跨设备任务调度与协同实战:算力分配、音视频协同与智能家居联动 在万物互联的全场景时代,设备间的高效协同是释放分布式系统潜力的关键。HarmonyOS NEXT通过分布式任务调度技术,实现了跨设备算力动态分配与任务无缝流转&#…...
Elasticsearch 海量数据写入与高效文本检索实践指南
Elasticsearch 海量数据写入与高效文本检索实践指南 一、引言 在大数据时代,企业和组织面临着海量数据的存储与检索需求。Elasticsearch(以下简称 ES)作为一款基于 Lucene 的分布式搜索和分析引擎,凭借其高可扩展性、实时搜索和…...

jenkins集成gitlab发布到远程服务器
jenkins集成gitlab发布到远程服务器 前面我们讲了通过创建maven项目部署在jenkins本地服务器,这次实验我们将部署在远程服务器,再以nginx作为前端项目做一个小小的举例 1、部署nginx服务 [rootweb ~]# docker pull nginx [rootweb ~]# docker images …...
AI问答-vue3+ts+vite:http://www.abc.com:3022/m-abc-pc/#/snow 这样的项目 在服务器怎么部署
为什么记录有子路径项目的部署,因为,通过子路径可以区分项目,那么也就可以实现微前端架构,并且具有独特优势,每个项目都是绝对隔离的。 要将 Vue3 项目(如路径为 http://www.abc.com:3022/m-saas-pc/#/sno…...

当主观认知遇上机器逻辑:减少大模型工程化中的“主观性”模糊
一、人类与机器的认知差异 当自动驾驶汽车遇到紧急情况需要做出选择时,人类的决策往往充满矛盾:有人会优先保护儿童和老人,有人坚持"不主动变道"的操作原则。这种差异背后,体现着人类特有的情感判断与价值选择。而机器的…...