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

news2025/6/7 22:52:25

文章目录

  • 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"] = 24

fmt.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.coloradmin.cn/o/2403433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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、搭建环境 首先&#xf…

跨界破局者鲁力:用思辨与创新重塑汽车流通行业标杆

来源:投资家 在汽车流通行业深度变革的浪潮中,东莞东风南方汽车销售服务有限公司塘厦分公司总经理鲁力历经近二十年行业深耕,构建了一条从汽车销售顾问到区域运营掌舵者的进阶范本。作为东风日产体系内兼具理论建构与实战穿透力的标杆管理者…

OS11.【Linux】vim文本编辑器

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

基于SFC的windows系统损坏修复程序

前言 在平时使用Windows操作系统时会遇到很多因为系统文件损坏而出现的错误 例如:系统应用无法打开 系统窗口(例如开始菜单)无法使用 电脑蓝屏或者卡死 是如果想要修复很多人只能想到重装系统。但其实Windows有一个内置的系统文件检查器可以修复此类错误。 原理 SFC命令…

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

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

Vue 3 弹出式计算器组件(源码 + 教程)

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

监测预警系统重塑隧道安全新范式

在崇山峻岭的脉络间延伸的隧道,曾是交通安全的薄弱环节。智慧隧道监测预警系统的诞生,正在彻底改变这种被动防御格局,通过数字神经网络的构建,为地下交通动脉注入智能守护基因。 一、安全防控体系的质变升级 1.风险感知维度革命…

技巧小结:外部总线访问FPGA寄存器

概述 需求:stm32的fsmc总线挂载fpga,stm32需要访问fpga内部寄存器 1、分散加载文件将变量存放到指定地址即FPGA寄存器地址 sct文件指定变量存储地址,从而可以直接访问外设,(28335也可以,不过用的是cmd文件…

jenkins集成gitlab发布到远程服务器

jenkins集成gitlab发布到远程服务器 前面我们讲了通过创建maven项目部署在jenkins本地服务器,这次实验我们将部署在远程服务器,再以nginx作为前端项目做一个小小的举例 1、部署nginx服务 [rootweb ~]# docker pull nginx [rootweb ~]# docker images …

当主观认知遇上机器逻辑:减少大模型工程化中的“主观性”模糊

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

会计 - 金融负债和权益工具

一、金融负债和权益工具区分的基本原则 (1)是否存在无条件地避免交付现金或其他金融资产的合同义务 如果企业不能无条件地避免以交付现金或其他金融资产来履行一项合同义务,则该合同义务符合金融负债的义务。 常见的该类合同义务情形包括:- 不能无条件避免的赎回; -强制…

Dify工具插件开发和智能体开发全流程

想象一下,你正在开发一个 AI 聊天机器人,想让它能实时搜索 Google、生成图像,甚至自动规划任务,但手动集成这些功能耗时又复杂。Dify 来了!这个开源的 AI 应用平台让你轻松开发工具插件和智能体策略插件,快…

AI书签管理工具开发全记录(十三):TUI基本框架搭建

文章目录 AI书签管理工具开发全记录(十三):TUI基本框架搭建前言 📝1.TUI介绍 🔍2. 框架选择 ⚙️3. 功能梳理 🎯4. 基础框架搭建⚙️4.1 安装4.2 参数设计4.3 绘制ui4.3.1 设计结构体4.3.2 创建头部4.3.3 创…

初识结构体,整型提升及操作符的属性

目录 一、结构体成员访问操作符1.1 结构体二、操作符的属性:优先级、结合性2.1 优先级2.2 结合性C 运算符优先级 三、表达式求值3.1 整型提升3.2 算数转化 总结 一、结构体成员访问操作符 1.1 结构体 C语言已经提供了内置类型,如:char,shor…

检测到 #include 错误。请更新 includePath。已为此翻译单元(D:\软件\vscode\test.c)禁用波形曲线

原文链接:【VScodeMinGw】安装配置教程 下载mingw64 打开可以看到bin文件夹下是多个.exe文件,gcc.exe地址在环境配置中要用到 原文链接:VSCode中出现“#include错误,请更新includePath“问题,解决方法 重新VScode后…

2025年,百度智能云打响AI落地升维战

如果说从AI到Agent是对于产品落地形态的共识,那么如今百度智能云打响的恰是一个基于Agent进行TO B行业表达的AI生产力升维战。 在这个新的工程体系能力里,除了之前百度Create大会上提出的面向Agent的RAG能力等通用能力模块,对更为专业、个性…

Seed1.5-VL登顶,国产闭源模型弯道超车丨多模态模型5月最新榜单揭晓

随着图像、文本、语音、视频等多模态信息融合能力的持续增强,多模态大模型在感知理解、逻辑推理和内容生成等任务中的综合表现不断提升,正在展现出愈发接近人类的智能水平。多模态能力也正在从底层的感知理解,迈向具备认知、推理、决策能力的…

第3章——SSM整合

一、整合持久层框架MyBatis 1.准备数据库表及数据 创建数据库:springboot 使用IDEA工具自带的mysql插件来完成表的创建和数据的准备: 创建表 表创建成功后,为表准备数据,如下: 2.创建SpringBoot项目 使用脚手架创建…

VTK 显示文字、图片及2D/3D图

1. 基本环境设置 首先确保你已经安装了VTK库&#xff0c;并配置好了C开发环境。 #include <vtkSmartPointer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkRenderer.h> 2. 显示文字 2D文字 #include &l…