01-数据类型之引用类型之集合
1、集合 map
1.1、map 的创建
Go 内置了 map 类型,map 是一个无序键值对集合(也有一些书籍翻译为字典)。
普通创建:
1 |
|
make 方式创建:
1 |
|
注意:gol 中 map 的 key 通常 key 为 int、string,但也可以是其他类型如:bool、数字、string、指针、channel,还可以是只包含前面几个类型的接口、结构体、数组。slice、map、function 由于不能使用 == 来判断,不能作为 map 的 key。
1.2、map 的使用
通过key操作元素:
1 |
|
map 的遍历:同数组一样,使用 for-range 的结构遍历
注意:
- map 是无序的,每次打印出来的 map 都会不一样,它不能通过 index 获取,而必须通过 key 获取;
- map 的长度是不固定的,也就是和slice一样,也是一种引用类型
- 内置的 len 函数同样适用于 map,返回 map 拥有的 key 的数量
- go 没有提供清空元素的方法,可以重新 make 一个新的 map,不用担心垃圾回收的效率,因为 go 中并行垃圾回收效率比写一个清空函数高效很多
- map 和其他基本类型不同,它不是 thread-safe,在多个 go-routine 存取时,必须使用 mutex lock 机制
1.3、并发安全的 map
演示并发读写 map 的问题:
1 |
|
编译会有错误提示:fatal error: concurrent map read and map write
,即出现了并发读写,因为用两个并发程序不断的对map进行读和写,产生了竞态问题。map内部会对这种错误进行检查并提前发现。
Go 内置的 map 只有读是线程安全的,读写是线程不安全的。
需要并发读写时,一般都是加锁,但是这样做性能不高,在go1.9版本中提供了更高效并发安全的sync.Map。
sync.Map的特点:
- 无须初始化,直接声明即可
sync.Map
不能使用 map 的方式进行取值和设值操作,而是使用sync.Map
的方法进行调用。Store 表示存储,Load 表示获取,Delete 表示删除。- 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,需要继续迭代时,返回 true,终止迭代返回 false。
1 |
|
注意:map 没有提供获取 map 数量的方法,可以在遍历时手动计算。sync.Map
为了并发安全。损失了一定的性能。
01-数据类型之引用类型之集合
https://flepeng.github.io/021-Go-31-Go-基础-01-数据类型之引用类型之集合/