《Go程序设计语言》学习笔记之map

一. 环境

  Centos8.5, go1.17.5 linux/amd64

二. 概念

1) 散列表,是一个拥有键值对元素的无序集合。在这个集合中,键是唯一的,键对应的值可以通过键来获取、更新或移除。在Go语言中,map 是散列表的引用,map 的类型是 map[k]v ,其中 k 和 v 是字典的键和值对应的数据类型。

map 中所有的键都拥有相同的类型,同时所有的值也都拥有相同的数据类型,但是键的类型和值的类型不一定相同。

2) 键的类型 k,必须是可以通过操作符 == 来进行比较的数据类型,所以 map 可以检测某一个键是否已经存在。

三. 声明/初始化

方式一. 使用 make,声明一个 map 变量 ages,此时,它会初始化为一个空 map。

  8 func main() {
9 ages := make(map[string]int)
10
11 fmt.Println(ages == nil)
12 fmt.Println(ages)
13 }

  运行结果如下,此时 ages 是一个空 map,并非零值 nil。

声明新的空 map 的另一种方式,如下

  8 func main() {
9 ages := map[string]int{}
10
11 fmt.Println(ages == nil)
12 fmt.Println(ages)
13 }

  运行结果如下

方式二. 使用 map 的字面量来新建一个带初始化键值对元素的字典。注意第11行代码,如果大括号 } 换行,则第11行后面须有逗号,否则不用加逗号。

  8 func main() {
9 ages := map[string]int{
10 "Alice": 31,
11 "Bog": 34,
12 }
13
14 fmt.Println(ages)
15 }

  运行结果如下

这个与下面等价

  8 func main() {
9 ages := make(map[string]int)
10 ages["Alice"] = 31
11 ages["Bob"] = 34
12
13 fmt.Println(ages)
14 }

  运行结果如下

四. 访问

1) 更新键对应的值

  8 func main() {
9 ages := map[string]int{
10 "Alice": 31,
11 "Bob": 34,
12 }
13
14 ages["Alice"] = 30
15
16 fmt.Printf("age: %d\n", ages["Alice"])
17 }

  运行结果如下

2) 删除指定的元素

  8 func main() {
9 ages := map[string]int{
10 "Alice": 31,
11 "Bob": 34,
12 }
13
14 delete(ages, "Alice")
15
16 fmt.Println(ages)
17 }

  运行结果如下

3) 遍历

a. 结合 range 关键字遍历

  8 func main() {
9 ages := map[string]int{
10 "Alice": 31,
11 "Bob": 34,
12 "Smith": 23,
13 }
14
15 for k, v := range ages {
16 fmt.Printf("%5s: %d\n", k, v)
17 }
18 }

  运行结果如下

b. 按照指定的顺序遍历 map 中的元素。第19行代码,只需要 ages 中所有键,忽略了循环中的第二个变量。第23行代码,按照指定的顺序将 names 中的元素进行排序,然后按照这个顺序遍历 ages 中的值。

  9 func main() {
10 ages := map[string]int{
11 "David": 18,
12 "Smith": 23,
13 "Alice": 31,
14 "Bob": 34,
15 }
16
17 names := make([]string, 0, len(ages))
18
19 for k := range ages {
20 names = append(names, k)
21 }
22
23 sort.Strings(names)
24
25 for _, name := range names {
26 fmt.Printf("%5s: %d\n", name, ages[name])
27 }
28 }

  运行结果如下

五. 零值与判断元素是否存在

1) map 的零值是 nil,即没有引用任何散列表。

  8 func main() {
9 var ages map[string]int
10
11 fmt.Println(ages)
12 fmt.Println(nil == ages)
13 fmt.Printf("len: %d\n", len(ages))
14 }

  运行结果如下

许多操作可以在安全地在 map 的零值 nil 上执行,如查找元素、删除元素、获取 map 元素的个数(len),执行 range 循环,这些和空 map 的行为一致。

但是是向零值 map 中设置元素会导致错误。所以,设置元素前,必须初始化 map。

  4 func main() {
5 var ages map[string]int
6
7 ages["Alice"] = 27
8 }

  运行结果如下

2) 判断元素是否存在

通过下标的方式访问 map 中的元素总是会有值。如果键在 map 中,你将得到键对应的值;如果键不在 map 中,你将得到 map 值类型的零值。

有时,需要知道一个元素是否在 map 中。如果元素的类型是数值类型,我们就需要分辨一个不存在的元素和恰好这个元素的值是0的情况,因为 map[k]均为0。方式如下

  8 func main() {
9 ages := make(map[string]int)
10
11 ages["Alice"] = 27
12
13 if value, ok := ages["Bog"]; !ok {
14 fmt.Println("not exist")
15 } else {
16 fmt.Printf("%d\n", value)
17 }
18 }

  如第13行代码这种方式访问 map 中的元素输出两个值,第二个值是一个布尔值,用来报告该元素是否存在。这个布尔变量一般叫作 ok,尤其是它立即用在 if 条件判断中的时候。 

  运行结果如下

六. 比较

1) 和 slice 一样,map 不可直接进行比较,唯一合法的直接比较就是和 nil 做比较。为了判断两个 map 是否拥有相同的键和值,必须要写一个循环。

2) 当遇到不可直接比较的键类型,而又需要进行比较时,可以进行自定义一种比较方法来实现。

七. 实现集合类型的功能

Go没有提供集合类型,因为键都是唯一的,可以通过 map 来实现这一功能。比如使用 map[string]bool 的方式描述一个简单的集合。

八. 注意

无法获取 map 元素的地址。

  4 func main() {
5 ages := make(map[string]int)
6
7 ages["Alice"] = 27
8
>> 9 _ := &ages["Alice"]
10 }

  运行结果如下,编译报错 “无法获取 map 元素的地址”。原因:由于 map 的增长可能会导致已有元素被重新散列到新的存储位置,这样就可能使得获取的地址无效。

《Go程序设计语言》学习笔记之map的更多相关文章

  1. C程序设计语言学习笔记

    在Windows下运行C语言程序 Windows下的编程工具使用 VC 6.0,下面讲解如何在VC 6.0下运行上节的"Hello, world"程序. 1) 新建Win32 Co ...

  2. Go语言学习笔记十三: Map集合

    Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...

  3. 2017-04-21周C语言学习笔记

    C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...

  4. 2017-05-4-C语言学习笔记

    C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...

  5. GO语言学习笔记(一)

    GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...

  6. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  7. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  8. Go语言学习笔记六: 循环语句

    Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...

  9. Go语言学习笔记二: 变量

    Go语言学习笔记二: 变量 今天又学了一招如何查看go的版本的命令:go version.另外上一个笔记中的代码还可以使用go run hello.go来运行,只是这种方式不会生成exe文件. 定义变 ...

  10. Go语言学习笔记(1)——顺序编程

    Go语言学习笔记这一堆主要是<Go语言编程>(人民邮电出版社)的读书笔记.中间会穿插一些零碎的点,比如源码学习之类的.大概就是这样吧. 1. 顺序编程 1.1 变量 变量的声明: var ...

随机推荐

  1. Nginx 简介 转载:https://www.cnblogs.com/wztshine/p/16162640.html

    Nginx 安装环境 安装 gcc 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装: yum install gcc-c++ 安装 PCR ...

  2. CF327C Magic Five 题解

    题目传送门 前置知识 等比数列求和公式 | 乘法逆元 解法 设 \(lena\) 表示 \(a\) 的长度. 首先,若一个数能被 \(5\) 整除,则该数的末尾一定为 \(0\) 或 \(5\).故考 ...

  3. NVME(学习笔记一)—概述

    NVMe概述 NVMe是一个针对基于PCIe的固态硬盘的高性能的.可扩展的主机控制器接口. NVMe的显著特征是提供多个队列来处理I/O命令.单个NVMe设备支持多达64K个I/O 队列,每个I/O队 ...

  4. 从零开始手写 mybatis(二)mybatis interceptor 插件机制详解

    前景回顾 第一节 从零开始手写 mybatis(一)MVP 版本 中我们实现了一个最基本的可以运行的 mybatis. 常言道,万事开头难,然后中间难. mybatis 的插件机制是 mybatis ...

  5. Amlogic电视盒子红外遥控适配笔记

    前一阵做了个安卓6的固件, 在R3300L和Q7上跑的, 其他问题没有, 但是有用户反映原来的遥控器用不了了, 于是检查了一下遥控器配置, 顺便学习一下此类设备的红外遥控机制. 为了方便测试还上淘宝买 ...

  6. MutationObserver对象

    MutationObserver对象 MutationObserver (W3C DOM4)对象提供了监视对DOM树所做更改的能力,其被设计为旧的Mutation Events功能的替代品(该功能是D ...

  7. eslint+prettier 统一代码风格

    1.实现效果 Eslint校验代码语法,prettier统一格式化代码,按下保存自动修复eslint错误,自动格式化代码. 2.安装vscode插件 Vetur ESLint Prettier - C ...

  8. r0capture 原理分析

    r0capture 是比较好用的抓包工具 仅限安卓平台,测试安卓7.8.9.10.11.12 可用 : 无视所有证书校验或绑定,不用考虑任何证书的事情: 通杀TCP/IP四层模型中的应用层中的全部协议 ...

  9. LayUI框架应用常见问题

    https://layui.itze.cn/index.html LayUI框架文档主页 获取URL参数 诸如表格中的"编辑","详情"工具按钮,需要在弹出层页 ...

  10. 详解SSL证书系列(2)SSL证书对网站的好处

    在如今谷歌.百度等互联网巨头强制性要求网站 HTTPS 化的情况下, 网站部署 SSL 证书已然成为互联网的发展趋势,我们也知道了 SSL证书可以防止网络安全威胁.那么除此外为网站部署 SSL 证书还 ...