吃透 Golang 基础:数据结构之 Map

article/2025/6/13 10:36:28

文章目录

  • 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,其中KV分别对应 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 作为有意义的结果。


http://www.hkcw.cn/article/IqRNujqlwf.shtml

相关文章

手机邮箱APP操作

收发电子邮件方式 邮箱可以在网络段登录,也可以在手机端登录。 大学网络服务 收发电子邮件有三种方式: 1、Web方式: 1)登录“网络服务”(https://its.pku.edu.cn),点页面顶端“邮箱”。 2&…

Spring AI之RAG入门

目录 1. 什么是RAG 2. RAG典型应用场景 3. RAG核心流程 3.1. 检索阶段 3.2. 生成阶段 4. 使用Spring AI实现RAG 4.1. 创建项目 4.2. 配置application.yml 4.3. 安装ElasticSearch和Kibana 4.3.1. 安装并启动ElasticSearch 4.3.2. 验证ElasticSearch是否启动成功 …

Spring AI Alibaba + Nacos 动态 MCP Server 代理方案

作者:刘宏宇,Spring AI Alibaba Contributor 文章概览 Spring AI Alibaba MCP 可基于 Nacos 提供的 MCP server registry 信息,建立一个中间代理层 Java 应用,将 Nacos 中注册的服务信息转换成 MCP 协议的服务器信息&#xff0c…

19-项目部署(Linux)

Linux是一套免费使用和自由传播的操作系统。说到操作系统,大家比较熟知的应该就是Windows和MacOS操作系统,我们今天所学习的Linux也是一款操作系统。 我们作为javaEE开发工程师,将来在企业中开发时会涉及到很多的数据库、中间件等技术&#…

2025.6.3学习日记 Nginx 基本概念 配置 指令 文件

1.初始nginx Nginx(发音为 “engine x”)是一款高性能的开源 Web 服务器软件,同时也具备反向代理、负载均衡、邮件代理等功能。它由俄罗斯工程师 Igor Sysoev 开发,最初用于解决高并发场景下的性能问题,因其轻量级、高…

SpringCloud——Nacos注册中心、OpenFeign

一、Nacos注册中心 1.注册中心原理 2.服务注册 添加依赖&#xff1a; <!--nacos 服务注册发现--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dep…

WAF绕过,网络层面后门分析,Windows/linux/数据库提权实验

一、WAF绕过文件上传漏洞 win7&#xff1a;10.0.0.168 思路&#xff1a;要想要绕过WAF&#xff0c;第一步是要根据上传的内容找出来被拦截的原因。对于文件上传有三个可以考虑的点&#xff1a;文件后缀名&#xff0c;文件内容&#xff0c;文件类型。 第二步是根据找出来的拦截原…

榕壹云健身预约系统:多门店管理的数字化解决方案(ThinkPHP+MySQL+UniApp实现)

随着全民健身热潮的兴起,传统健身房在会员管理、课程预约、多门店运营等方面面临诸多挑战。针对这一需求,我们开发了一款基于ThinkPHP+MySQL+UniApp的榕壹云健身预约系统,为中小型健身机构及连锁品牌提供高效、灵活的数字化管理工具。本文将详细介绍系统的技术架构、核心功能…

nginx去掉暴漏外边的版本号

背景 在做安全扫描的时候&#xff0c;对方说nginx会暴漏版本号属于中危漏洞 解决方法 nginx 在http{括号里增加 server_tokens off; # 关闭版本号显示# add_header Server "Apache/2.4.3"; # 伪造为 Apache 服务器&#xff08;可选&#xff09;效果

飞牛fnNAS存储模式RAID 5数据恢复

目录 一、添加硬盘 二、创建RAID 5 存储空间 三、上传测试文件 四、拆除硬盘 五、更换硬盘 六、修复RAID 5 七、验证其内文件 八、NAS系统崩溃后的数据盘 前文《飞牛fnNAS存储空间模式详解》 中介绍了fnNAS存储空间的几个模式,细心的网友应该能感受到,我是非常推崇R…

OpenEMMA: 打破Waymo闭源,首个开源端到端多模态模型

1. 概述 OpenEMMA&#xff08;Open-source End-to-end Multimodal Model for Autonomous driving&#xff09;是由德州农工大学、密歇根大学和多伦多大学联合推出的开源端到端自动驾驶多模态模型框架&#xff0c;旨在复现并开源 Waymo 旗下 EMMA 系统的核心思路与方法。 该框…

学习STC51单片机26(芯片为STC89C52RCRC)

每日一言 真正的强者&#xff0c;不是没有眼泪&#xff0c;而是含着泪依然奔跑。 硬件&#xff1a;4G模块 这个是接线原理&#xff0c;我们也只要知道这个4根线的连接就好了&#xff0c;我们也是连接到USB转TTL的模块上 要插卡哈......... 随后我们下载一个叫做亿佰特的调试助…

GROM快速上手

&#x1f43e; 个人主页 &#x1f43e; 阿松爱睡觉&#xff0c;横竖醒不来 &#x1f3c5;你可以不屠龙&#xff0c;但不能不磨剑&#x1f5e1; 目录 一、概要二、上手步骤&#xff08;一&#xff09;安装 GORM&#xff08;二&#xff09;连接数据库&#xff08;三&#xff09;定…

MATLAB仿真生成无线通信网络拓扑推理数据集

一、数据集生成程序 %创建时间&#xff1a;2025年6月3日 %用途&#xff1a;生成不同节点样本&#xff0c;统计稀疏性约束情况 %zhouzhichaoclose all clearfor n [20,30,40,50]dataset_n 100;nodes_P ones(n,1);for Sampling_M [3000]%获取一帧信号及对应功率[ack,fs] ac…

【OCCT+ImGUI系列】012-Geom2d_AxisPlacement

Geom2d_AxisPlacement 教学笔记 一、类概述 Geom2d_AxisPlacement 表示二维几何空间中的一个坐标轴&#xff08;轴系&#xff09;&#xff0c;由两部分组成&#xff1a; gp_Pnt2d&#xff1a;原点&#xff08;Location&#xff09;gp_Dir2d&#xff1a;单位方向向量&#xff…

NodeMediaEdge任务管理

NodeMediaEdge任务管理 简介 NodeMediaEdge是一款部署在监控摄像机网络前端中&#xff0c;拉取Onvif或者rtsp/rtmp/http视频流并使用rtmp/kmp推送到公网流媒体服务器的工具。 在未使用NodeMediaServer的情况下&#xff0c;或是对部分视频流需要单独推送的需求&#xff0c;也可…

ROS2学习(18)------ROS2 Rviz工具使用说明

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 ROS版本&#xff1a;2 ROS 2 中的 Rviz&#xff08;Robot Visualization&#xff09;是一个强大的三维可视化工具&#xff0c;用于显示来自 ROS 系统的各种传感器数据、路径规划结果、机器人…

安科瑞APD300:多模态融合的智能局放监测新标杆

安科瑞顾强 在电网安全运行的严密链条中&#xff0c;开关柜、环网柜等高压设备如同关键节点&#xff0c;其内部绝缘状态的完好性直接决定着电力系统的整体稳定。局部放电&#xff08;PD&#xff09;作为绝缘劣化的早期、灵敏征兆&#xff0c;若能及时捕捉和精准识别&#xff0…

Office文档图片批量导出工具

软件介绍 本文介绍一款专业的Office文档图片批量导出工具。 软件特点 这款软件能够批量导出Word、Excel和PPT中的图片&#xff0c;采用绿色单文件设计&#xff0c;体积小巧仅344KB。 基本操作流程 使用方法十分简单&#xff1a;直接将Word、Excel或PPT文件拖入软件&#xf…

网络编程(计算机网络基础)

认识网络 1.网络发展史 ARPnetA(阿帕网)->internet(因特网)->移动互联网->物联网 2.局域网与广域网 局域网 概念&#xff1a;的缩写是LAN&#xff08;local area network&#xff09;&#xff0c;顾名思义&#xff0c;是个本地的网络&#xff0c;只能实现小范围短距…