学习 go 的映射 map¶
Quote
"Go is like a better C, from the guys that didn’t bring you C++." – Ikai Lan
映射(map)¶
本章介绍映射,在很多编程语言中都有类似的用来保存键值对(key-value)的数据结构,比如 python 中的 dict, c++ 中的 map。一般底层使用哈希 表或者红黑树来实现 map,查询效率是非常高的。如果你熟悉其他语言的 map 结构,上手 go 的 map 非常容易。
Go 也内置了 map 数据结构,作为 map 的 key,必须要是支持 == 和 != 操作符的类型,常用的基础类型 int, float64, string 等都是可以作为 map 的键的,但是像切片或者不能比较的结构体无法作为键。而映射的值没有要求,任何内置或者自定义的类型都可以作为值,这样一来 我们可以创建复杂的嵌套 map 结构,比如 map 的 value 值依然是一个 map。
先来看下如何去创建一个映射,同样也有几种形式,最常用的方式就是使用内置的 make 函数:
1 2 3 4 5 6 7 8 |
|
再来看一下 map 的操作,和 python 比较类似。
Warning
这里需要注意的就是使用 v := m[k]
这种方式获取值,如果相应的 k 不存在,map 不会像 python 一样抛错(KeyError),而是直接给
你返回一个类型的零值(数字是0,字符串是空串),这个可能不是你期望的,所以一般我们用 v, found := m[k]
这种语法,如果不存
在 k 的话,found 的值是 false,这样就知道究竟是否存在这个 k 了。
我们同样编写一些小的测试代码来熟悉 map 的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
如何实现 set?¶
set 经常在讲 map 的时候提到,它是集合类型,和数学上的集合概念类似,保存唯一的值的容器,经常用来判断一个元素是否已经存在 。go 里不像 python 直接提供了一个内置 set 类型,但其实根据 map 我们也可以用来实现一个简单的 set 结构,只需要创建一个 map ,然后让 map 的值是 bool 类型,标识是否存在即可。
1 2 3 4 5 6 7 8 9 |
|
练习¶
- 尝试编写一个词频统计程序,你需要查询下如何用 go 读取文件,然后统计每个单词出现的次数?
- 给你一个有重复数字的 []int slice,请你用 map 实现一个去重函数
func unique(intVals []int) []int
- 内置的 map 并不是并发安全的,怎么样修改才是并发安全的呢?