go中map哈希表使用总结

news2024/11/24 16:17:15

作者:程序员CKeen
博客:http://ckeen.cn​​​​​​​

长期坚持做有价值的事!积累沉淀,持续成长,升维思考!希望把编码做为长期爱好😄


在 Go 语言中,map是一种基于哈希表实现的数据结构。哈希表是一种方便且功能强大的内置数据结构,它是一个无序的key/value键值对的集合。

哈希表一般写作map[K]V,其中K代表键,V代表K对应的值。哈希表通过给定的键Key可以在常数时间复杂度内检索、更新或删除对应的value,是一种比较常用的数据结构。

下面主要介绍一下map的具体的使用方法:

1.map的的几种创建方式

  • 直接创建一个空map​​​​​​​
    map1 := map[string]int {}       // 先创建一个空map,不包含任何键值对
    map1["foo"] = 1                 // 添加一个键值对
    map1["boo"] = 2
    map1["hello"] = 3
    fmt.Println(map1)
    // map[boo:2 foo:1 hello:3] ,可以看到打印的结果是无序的
  • 创建一个初始化键值对的map
  • map2 := map[string]int {       // 初始化创建一个包含键值对的map
        "foo": 1,
        "boo": 2,
        "hello" : 3,
    }
    fmt.Println(map2)
    // map[boo:2 foo:1 hello:3]

  • make内置函数创建。go中所有的引用类型都可以通过make来创建实例
    map3 := make(map[string]int)
    map3["foo"] = 1
    map3["boo"] = 2
    map3["bar"] = 3
    fmt.Println(map3)
    // map[bar:3 boo:2 foo:1]

2.map的操作

  1. 对map进行添加键值对操作
    map4 := make(map[string]int)
    map4["foo"] = 1
    map4["boo"] = 2
    map4["bar"] = 3
    map4["bar"] = 4
    fmt.Println(map4)
    // map[bar:4 boo:2 foo:1]
    创建一个map的集合对象后,只需要直接使用中括号添加key,然后=后面直接赋值即可。

    ​​​​​​​map的key/value使用需要注意的点
         1. ​​ ​​map的键可以是定义了相等运算符的任何类型,例如整数、浮点数和复数、字符串、指针、接口(只要动态类型支持相等)、结构体和数组。
         2. 切片不能用作映射键,因为它们没有定义相等。
         3. 虽然浮点数类型也是支持相等运算符比较的,但是将浮点数用做key类型,最坏的情况是可能出现的NaN和任何浮点数都不相等。
         4. map添加的时候如果该key已经存在,则会覆盖该键对应的值,而不会报错。
  • 对map进行取值操作
    map4 := make(map[string]int)
    map4["foo"] = 1
    map4["boo"] = 2
    map4["bar"] = 3
    map4["bar"] = 4
    barVal := map4["bar"]
    fmt.Println(map4,barVal)
    // map[bar:4 boo:2 foo:1] 4
    
    hello := map4["hello"]
    fmt.Println(hello)
    // 打印 0
    barVal2 := &map4["bar"]  //Cannot take the address of 'map4["bar"]'
    map中进行取值操作,如果key不存在的时候,它不会报错, 它会返回value的零值。而且map中的value值并不是一个变量,因此我们不能对map的元素进行取址操作
  • 对map的删除操作
    map4 := make(map[string]int)
    map4["foo"] = 1
    map4["boo"] = 2
    map4["bar"] = 3
    delete(map4,"bar")
    fmt.Println(map4)
    直接使用go的库函数delete就可以完成删除key/value操作,当key不存在的时候,delete操作也不会报错,也没有任何反馈信息。因此如果你想知道是否你删除的键值对是否有删除, 可以先判断该键值对是否存在。
  • 对map的遍历操作
    map6 := make(map[string]int)
    map6["foo"] = 1
    map6["boo"] = 2
    map6["bar"] = 3
    map6["hello"] = 5
    for k, val := range map6 {
    	fmt.Printf("key:%v,value:%v\n",k,val)
    }
    // key:foo,value:1
    // key:boo,value:2
    // key:bar,value:3
    // key:hello,value:5
    遍历map中全部的key/value对,使用range风格的for循环实现,和之前的slice遍历语法类似。map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。实际遍历的顺序是随机的,每一次遍历的顺序都不相同。

    如果我们想对map进行排序,则我们必须显式地对key使用slice进行排序,然后根据slice中key的顺序,去map中取值。
    var keys []string
    for key := range map4 {
    	keys = append(keys, key)
    }
    sort.Strings(keys)
    for _, val := range map4 {
        fmt.Printf("%s\t%d\n", val, ages[val])
    }
  • 判断map的key的是否存在
    map7 := map[string]int {   // 初始化创建
        "foo": 1,
        "boo": 2,
        "hello" : 3,
        "test" : 0 
    }
    fmt.Println(map7["test"],map7["world"])
    // 打印的为零值 0 0
    
    if val, ok := map7["world"]; ok {
    	fmt.Println(val)
    }
    // 不会打印结果
    当前map的键不存在的时候,取到的值默认为零值。这样就存在当取到为零值的时候,无法判断到底是键不存在,还是存得键本身就为零值的情况,所以go利用多返回值的形式,可以来判断是否。

    上述代码中,如果ok为true, 则说明对应的key存在。
    ​​​​​​​
    为了测试是否存在于映射中而不考虑实际值,可以使用空白标识符(_)来代替通常的值变量。

3.map中使用的时候要注意点

  • 与切片一样,map了保存对底层数据结构的引用。如果函数接受map参数,则调用者可以看到它对map元素所做的更改,类似于传递指针。
    我们如果不想函数内部修改影响传入的map结构时,先进行复制操作是比较好的做法。

    同样如果我们结构内部对外的暴露的是一个map结构,如果不想外面的修改影响到内部的mpa结构,也可以将对外暴露的结构进行复制一个新的对外。

     ​​​​​

  • 在使用 map 时,需要注意并发安全性。如果多个 goroutine 同时读写同一个 map,可能会导致数据竞争的问题。可以使用 sync 包中的锁机制来保证并发安全。也可以是用sync.Map结构
  • 在使用 map 时,需要注意内存占用。如果 map 中存储了大量的数据,可能会导致内存占用过高,从而影响程序的运行效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/685179.html

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

相关文章

设计模式之解释器模式笔记

设计模式之解释器模式笔记 说明Interpreter(解释器)目录解释器模式示例类图抽象表达式类环境角色类封装变量的类加法表达式类减法表达式类测试类 说明 记录下学习设计模式-解释器模式的写法。JDK使用版本为1.8版本。 Interpreter(解释器) 意图:定义一个语言,定义…

chatgpt赋能python:Python编程:如何将程序变成软件

Python编程:如何将程序变成软件 Python是一种非常流行的编程语言,因为它具有简单易学、高效和灵活等优点。许多人使用Python编写程序,但他们可能不知道如何将这些程序变成可执行的软件。在本文中,我们将介绍Python程序如何成为软…

【C/C++数据结构】链表与快慢指针

目录 一、单链表 二、双向循环链表 三、判断链表是否带环 四、链表的回文结构判断 五、复制带随机指针的链表 一、单链表 优点:头部增删效率高,动态存储无空间浪费 缺点:尾部增删、遍历效率低,不支持随机访问节点 头结点&…

【Linux | Shell】bash shell 基础命令

目录 一、概述二、启动shell2.1 用户的默认 Shell 程序2.2 Shell 提示符 三、 基础命令3.1、man 命令3.2、cd 命令3.3、ls命令 一、概述 很多 Linux 发行版的默认 shell 是 GNU bash shell。本文将介绍 bash shell 的基本特性,比如 bash 手册、命令行补全以及如何显…

JavaWeb 第一个Servlet程序

1.Servlet Servlet是Java编写的用于Web应用程序的服务器端程序。 它可以接收来自Web浏览器的HTTP请求并生成响应。 Servlet通常用于创建动态Web内容,例如网页、表单处理、登录和数据库访问等。 Servlet是Java EE(Enterprise Edition)规范…

[补充]托福口语21天——day2 课堂内容

day1 课堂:http://t.csdn.cn/cyvZm day1 语料:http://t.csdn.cn/syTBy 目录 1 时间准备 2 例题 3 答题步骤 3.1 范例 3.2 范例 4 连接词 5 完整回答 5.1 范例 5.2 范例 6 总结 背背背! 1. 如今的生活成本非常高。人们要付…

学习系统编程No.25【核心转储实战】

引言: 北京时间:2023/6/16/8:39,实训课中,大一下学期最后有课的一天,还有两天就要期末考啦!目前什么都还没有复习,不到星期天晚上,咱不慌,小小挂科,岂能拦得…

postgresql_internals-14 学习笔记(六)—— 统计信息

不完全来自这本书,把查到的和之前的文章重新汇总整理了一把。 一、 统计信息的收集 1. 主要参数 其中最主要的是track_counts,开启才会收集统计信息。 postgres# select name,setting,short_desc,context from pg_settings where name like track%; na…

LeetCode 周赛 351(2023/06/25)T2 有点意思

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问。 往期回顾:LeetCode 单周赛第 348 场 数位 DP 模版学会了吗? T1. 美丽下标对的数目(Easy) 标签&am…

python爬虫并做可视化分析--前程无忧

一.数据采集 1.采集逻辑 2.数据schema 招聘信息Schema { "岗位名称": "财务会计主管", "薪资":"1.3-2万", "地址": "*******", "经验要求": "5-7年", "公司名": "***…

JDK8新特性-上部

文章目录 一、Java发展史1.1 发展史1.2 OpenJDK和OracleJDK1.3 Open JDK 官网介绍 二、Lambda表达式2.1 需求分析2.2 Lamada表达式的体验2.3 Lambda表达式的语法规则2.3.1 Lambda表达式练习2.3.2 Lambda表达式练习 2.4 Lambda表达式的使用前提2.5 FunctionalInterface注解2.6 L…

MATLAB | 如何使用MATLAB获取顶刊《PNAS》绘图(附带近3年图像)

千呼万唤始出来,《PNAS》绘图获取的代码来啦,不过这次研究了半天也没想到如何获取付费文章的绘图,就只下载了免费文章(主要也怕侵权),不过光免费文章的图片三年了也有接近1.7w张了,同时使用代码下载时依旧需要科学上网…

【Redis】Redis的数据结构

【Redis】Redis的数据结构 文章目录 【Redis】Redis的数据结构1. 动态字符串SDS2. IntSet2.1 IntSet升级 3. Dict3.1 Dict的扩容3.2 Dict的收缩3.3 Dict的rehash 4. ZipList4.1 ZipList中的Entry4.1.1 Encoding编码 4.2 ZipList的连锁更新问题4.3 特性 5. QuickList 1. 动态字符…

【软考网络管理员】2023年软考网管初级常见知识考点(7)-生成树协议

涉及知识点 STP的原理,端口的状态,RSTP协议,MSTP协议,软考网络管理员常考知识点,软考网络管理员网络安全,网络管理员考点汇总。 原创于:CSDN博主-《拄杖盲学轻声码》,更多考点汇总可…

模拟电路系列分享-运放的关键参数2

目录 概要 整体架构流程 技术名词解释 1.输入偏置电流: 2.输入失调电流 技术细节 总结; 概要 提示:这里可以添加技术概要 实际运放与理想运放具有很多差别。理想运放就像一个十全十美的人,他学习100 分,寿命无限长,长…

Modal对话框(antd-design组件库)展示所有配置选项和onChange的作用

1.Modal对话框 模态对话框。 2.何时使用 需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以使用 Modal 在当前页面正中打开一个浮层,承载相应的操作。 另外当需要一个简洁的确认框询问用户时,可以使用 App.useApp 封装的…

创建微信小程序的几种方式

创建微信小程序的几种方式 1. 使用原生方式 在官网上下载微信开发者工具,之后使用微信开发者工具新建项目即可。 微信这边提供了多个模板,可以直接下载模板快速搭建上线,也可以使用空白模板根据需求自行编写。 空白模板项目结构&#xff1…

C语言:打印0-100000中的自幂数(水仙花数是其中一种)

题目: 求出 0~100000 之间的所有 自幂数 并输出。 自幂数是指一个n位数,其各位数字的n次方之和恰好等于该数本身, 如:153=1^3+5^3+3^3, 则153是一个自幂数。 思路: 总体…

【数据网格架构】分布式数据网格作为集中式数据单体的解决方案

企业数据架构师不应构建大型集中式数据平台,而应创建分布式数据网格。 ThoughtWorks 的首席技术顾问 Zhamak Dehghani 在旧金山 QCon 的演讲和相关文章中表示,这种方法的改变需要范式转变。随着数据变得越来越普遍,传统的数据仓库和数据湖架构…

Linux基础+命令操作+mysql、tomcat、nginx、RabbitMQ、Redis,ElasticSearch

配置代理 一、永久设置 //编辑配置文件 vi /etc/profile //在该配置文件的最后添加代理配置 export http_proxyhttp://f1336515:password10.137.255.169:3128 //代理服务器ip地址和端口号 export https_proxyhttp://f1336515:password10.137.255.169:3128 //代理服务器ip…