九、Go语言快速入门之map

文章目录

    • Map
      • :one: 使用`Map`
        • :star2: 声明和初始化
        • :star2: `map`容量
        • :star2: 用切片作为`map`的值
      • :two: 测试键值对是否存在及删除元素
      • :three: `For`-`range`
      • :four: `map`类型的切片
      • :five: map的排序
      • :six:将map的健和值对调

📦 使用版本为1.21.5

Map

在很多编程语言中都有map的存在,在Python中叫做字典,在java中也叫map,它的存储形式是key-value

1️⃣ 使用Map

🌟 声明和初始化

⭐️ map是引用类型,可以使用如下方法来声明一个map,注意只是声明一个map,而不是初始化

可以使用make来分配内存,不要使用new如果你错误的使用 new() 分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址

func main() {var map1 map[string]int     //声明一个map,基础方法 其中string为key的类型,int为value的类型map2 := make(map[string]int) //使用make这里是初始化map了map3 := map[string]int{"one":1,"two":2}
}
  • 在声明的时候不需要知道map的长度,它也是动态增长的
  • 未初始化的map的值是nil
  • key可以是任意能使用==或者!=操作符比较的类型(string,int,float),数组和切片、结构体不可以作为key,但是接口和指针类型可以(后面会学),如果需要用结构体来作为key,可以使用Key()Hash()方法通过计算结构体的域来计算出唯一的数字或者字符串的key(后面会学)
  • value可以是任意类型的,可以使用空接口类(后面会学),可以存储任意值,但是使用这种类型作为值时需要先做一次类型断言(后面会学)

map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了
多少数据。通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中
直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题

⭐️ map可以用函数作为value,这里就可以用来做分支结构,直接调用value对应的key来调用此函数

func main() {map1 := map[string]func() int{"one": func() int {return 1},"two": func() int {return 2},"three": func() int {return 3},}fmt.Println(map1) //输出的是地址
}map[one:0xe33c60 three:0xe33ca0 two:0xe33c80]//或者是
func main() {map1 := map[string]func(i int) int{"one": func(i int) int {return i},"two": func(i int) int {return i},"three": func(i int) int {return i},}fmt.Println(map1["one"](4)) //输出4
}

⭐️ 调用value的方法和数组类似,直接就是map名[key名]就好了,

func main() {map1 := map[string]int{"one": 1, "two": 2} //声明一个map,基础方法 其中string为key的类型,int为value的类型map1["three"] = 3                          //将map1的可以three的值改为3,如果没有这个key则添加test := map1["two"] //将指定key的赋予给test,如果key类型不存在则会被赋值为map1类型的空值fmt.Print(map1["one"], map1["two"], map1["three"], test)
}//输出
1 2 3 2

⭐️ 如果想要删除键值对,直接使用delete即可

	map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2}delete(map1, "four")
🌟 map容量

⭐️ map可以根据新增的key-value来动态的伸缩,因此它不存在固定长度或者最大限制,但是在初始化的时候可以选择表面map的初始容量

func main() {map1 := make(map[string]int,100) //在切片中使用make是一样的
}

map 增长到容量上限的时候,如果再增加新的key-value对,map 的大小会自动加 1。所以出于性能
的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明

🌟 用切片作为map的值

⭐️ 既然一个 key 只能对应一个 value,而 value 又是一个原始类型,那么如果一个 key 要对应多个值怎么
办?例如,当我们要处理unix机器上的所有进程,以父进程(pid 为整形)作为 key,所有的子进程(以
所有子进程的 pid 组成的切片)作为 value。通过将 value 定义为 []int 类型或者其他类型的切片,就可
以优雅的解决这个问题

func main() {map1 := make(map[int][]int)
}

2️⃣ 测试键值对是否存在及删除元素

⭐️ 在获取一个键值对时,就算哪个键不存在,也会返回一个value所属类型的空值,不好判断这个key是否存在,可以使用下面这种方法来判断是否存在

test 返回一个 bool 值:如果 two 存在于 map1two 就是 two 对应的 value 值,并且
testtrue;如果 two 不存在,va 就是一个空值,并且 test 会返回 false

func main() {var va intvar test boolmap1 := make(map[string]int)map1["one"] = 1int, test = map1["tow"] println(test, va)
}

3️⃣ For-range

⭐️ 和数组切片一样,但是map 不是按照 key 的顺序排列的,也不是按照 value 的序排列的

func main() {map1 := make(map[string]int)map1["one"] = 1map1["two"] = 2map1["three"] = 3for key, value := range map1 {println("Key: ", key, "Value: ", value)}
}//第一次输出
Key:  one Value:  1
Key:  two Value:  2
Key:  three Value:  3
//第二次输出
Key:  three Value:  3
Key:  one Value:  1
Key:  two Value:  2

4️⃣ map类型的切片

⭐️ 想获取一个 map 类型的切片,我们必须使用两次 make() 函数,第一次分配切片,第二次分配
切片中每个 map 元素

func main() {map1 := make([]map[string]int, 5) //分配切片for i := range map1 {map1[i] = make(map[string]int, 1) //分配切片中的每个map元素map1[i]["a"] = i}fmt.Print(map1)
}

⚠️ 错误方法

func main() {map1 := make([]map[string]int, 5)for _, test := range map1 {test = make(map[string]int, 1) //这里只是获取map的一个拷贝,并不是修改maptest["a"] = 2}fmt.Print(map1) 
}
//输出
[map[] map[] map[] map[] map[]]

5️⃣ map的排序

⭐️ map是无序的,如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序(使用 sort 包,然后可以使用切片的 for-range 方法打印出所有的 keyvalue

func main() {map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2}delete(map1, "four")test := make([]string, len(map1)) //创建一个切片,长度为map1的长度var i int                         //i为切片的索引for key, _ := range map1 {        //读取map的key值,存入对应索引的test切片test[i] = keyi++}sort.Strings(test)         //使用sort排序切片for _, key := range test { //去读按照切片内的值fmt.Printf("Key:%v,Value: %v ", key, map1[key])}
}//输出:
Key:five,Value: 5 Key:one,Value: 1 Key:three,Value: 3 Key:two,Value: 2

6️⃣将map的健和值对调

⭐️ 很难直接对map使用键和值对调,因为可能是键和值的类型不一样,

func main() {map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2} //初始mapmap2 := make(map[int]string, len(map1)) //键值对调后的mapfor k, v := range map1 {map2[v] = k}fmt.Println(map2)
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

平衡者:陈欣的宇宙使命

第一章 异象初现 2145年,地球已经不再是人类唯一的家园。随着科技的飞速发展,人类在银河系内建立了多个殖民星球。然而,这些新世界的繁荣背后隐藏着一个巨大的危机——各个星球之间的资源分配不均,导致了严重的社会动荡和冲突。 …

《AI产品经理手册》——解锁AI时代的商业密钥

在当今这个日新月异的AI时代,每一位产品经理都面临着前所未有的挑战与机遇,唯有紧跟时代潮流,深入掌握AI技术的精髓,才能在激烈的市场竞争中独占鳌头。《AI产品经理手册》正是这样一部为AI产品经理量身定制的实战宝典,…

React第十三章(useTransition)

useTransition useTransition 是 React 18 中引入的一个 Hook,用于管理 UI 中的过渡状态,特别是在处理长时间运行的状态更新时。它允许你将某些更新标记为“过渡”状态,这样 React 可以优先处理更重要的更新,比如用户输入&#x…

使用wordcloud与jieba库制作词云图

目录 一、WordCloud库 例子: 结果: 二、Jieba库 两个基本方法 jieba.cut() jieba.cut_for_serch() 关键字提取: jieba.analyse包 extract_tags() 一、WordCloud库 词云图,以视觉效果提现关键词,可以过滤文本…

2024年云手机推荐榜单:高性能云手机推荐

无论是手游玩家、APP测试人员,还是数字营销工作者,云手机都为他们带来了极大的便利。本文将为大家推荐几款在市场上表现优异的云手机,希望这篇推荐指南可以帮助大家找到最适合自己的云手机! 1. OgPhone云手机 OgPhone云手机是一款…

Template Method(模板方法)

1)意图 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2)结构 模板方法模式的结构图如图7-47 所示。 其中: AbstractClass(抽象类) 定义抽象的原语操作,具体…

自研小程序-心情追忆

在近期从繁忙的工作中暂时抽身之后,我决定利用这段宝贵的时间来保持我的Java技能不致生疏,并通过一个个人项目来探索人工智能的魅力。 我在Hugging Face(国内镜像站点:HF-Mirror)上发现了一个关于情感分析的练习项目&…

【设计模式】策略模式定义及其实现代码示例

文章目录 一、策略模式1.1 策略模式的定义1.2 策略模式的参与者1.3 策略模式的优点1.4 策略模式的缺点1.5 策略模式的使用场景 二、策略模式简单实现2.1 案例描述2.2 实现代码 三、策略模式的代码优化3.1 优化思路3.2 抽象策略接口3.3 上下文3.4 具体策略实现类3.5 测试 参考资…

【React】初学React

A. react中如何创建元素呢? 说明一点: 属性都改为驼峰形式(无障碍属性aria-*除外), class改成className 创建元素 B. 变量或表达式如何表示呢?大括号{ }包起来 变量值用大括号包裹 C. 元素和组件的区别 元素…

伦敦金价格是交易所公布的吗?

今年以来,伦敦金价格波动可谓是波澜壮阔,盘中屡次刷新历史新高,目前已经冲上了2700的历史大关。面对高歌猛进的伦敦金价格,投资者除了进行交易之外,还有一点相关方面的知识是想了解的。例如,伦敦金价格是交…

程序员也要认识下“信创产业”

兄弟姐妹们,大家初入社会会觉得技术是第一位,我呸,其实你在那个领域敲代码的选择才是最重要的,选对了领域绝对比你背上100个面试题目强,今天带大家了解下信创产业。 信创产业,即信息技术应用创新产业&#…

钉钉向广告低头

商业化重压下,钉钉试水应用内广告。 作者|文昌龙 编辑|杨舟 “钉钉吃相真心难看!早晨打卡时间还做开屏广告赚打工人的钱,比如很多踩点上班的,就因为你这5秒时间的开屏广告,没按上打卡按钮就会迟到,知道吗…

IDC报告解读:实用型靶场将成为下一代网络靶场的必然方向

——赛宁网安:回归用户需求,开创实用型靶场新范式 导读 本文基于《IDC TechScape:中国网络安全软件技术发展路线图,2024》中关于网络安全实训演练测试平台(靶场)的技术路线分析,结合国内外靶场…

RESTful风格

目录 一、什么是RESTful 1.1 RESTFul对WEB服务接口的规定包括: 1.2 REST对请求方式的具体约束如下: 1.3 REST对URL的具体约束如下: 1.4 RESTFul的核心概念: 二、RESTful风格与传统方式对比 三、RESTful风格演示 3.1 查询所…

openapi回调地址请求不通过

目录 1. 验证url接口get请求本地自测报错 2. 测试回调模式成功不返回结果 3. 测试回调模式返回结果带双引号 对接企业微信 产生会话回调事件 接口问题解决 1. 验证url接口get请求本地自测报错 java.lang.IllegalArgumentException: Last encoded character (before the pa…

砥砺十年风雨路,向新而行创新程丨怿星科技十周年庆典回顾

10月24日,是一年中的第256天,也是程序员节,同时也是怿星的生日。2014年到2024年,年华似水匆匆一瞥,多少岁月轻描淡写,怿星人欢聚一堂,共同为怿星科技的十周年庆生! 01.回忆往昔&…

C++:AVL树

目录 AVL树概念 AVL树的实现 AVL树的节点 AVL树的插入 AVL树的平衡调整 右单旋 左单旋 左右双旋 右左双旋 完整的插入函数 AVL树的查找 AVL树的验证 验证有序 验证平衡 完整代码 AVL树概念 AVL树是一种具有特殊性质的二叉搜索树,AVL树的左右子树也都…

Nginx线程模型

Nginx的线程模型具有其独特的设计特点,主要基于多进程和异步非阻塞的处理机制。以下是对Nginx线程模型的详细解析: 一、多进程模型 Nginx采用的是多进程模型,而非多线程模型。在这种模型中,Nginx会启动一个master进程和多个work…

【HTML】——VSCode 基本使用入门和常见操作

阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 零:HTML开发工具VSCode的使用 1:创建项目 2:创建格式模板&#x…

【C/C++】【三种方法】模拟实现strlen

学习目标: 使用代码模拟实现strlen。 逻辑: strlen 需要输入一个字符串数组类型的变量,并且返回一个整型类型的数据。strlen 需要计算字符串数组有多少个元素。 代码1:使用计数器 #define _CRT_SECURE_NO_WARNINGS 1 #include&…