golang map
什么是map?
map是一个可以存储key/value对的一种数据结构,map像slice一样是引用类型,map内部实现是一个hash table,因此在map中存入的数据是无序的(map内部实现)。而每次从map中读取的数据也是无序的,因为golang在设计之初,map迭代器的顺序就是随机的,有别于C/C++,虽然存入map的数据是无序的,但是每次从map中读取的数据是一样的(为什么每次读取顺序不一样)。
声明和初始化
// 声明一个map,因为map是引用类型,所以m是nil
var m map[KeyType]ValueType
// 初始化方式一,空map,空并不是nil
m := map[KeyType]ValueType{}
//初始化方式二,两种初始化的方式是等价的
m := make(map[KeyType]ValueType)
基本操作
m := map[string]int{}
// 增加一个key/value对
m["Tony"] = 10
// 删除Key Tony
delete(m, "Tony")
// 修改Key Tony的值
m["Tony"] = 20
// 判断某个Key是否存在
if _, ok := m["Tony"]; ok {
fmt.Println("Tony is exists")
}
// 遍历map
for key, value := range m {
fmt.Printf("Key = %s, Value = %d", key, value)
}
// 使用多个值对map进行初始化
mp := map[string]int {
"Tina": 10,
"Divad": 20,
"Tom": 5,
}
Key和Value可以使用什么类型?
Key :只要是可比较(可以使用==进行比较,两边的操作数可以相互赋值)的类型就可以,像整形,字符串类型,浮点型,数组(必须类型相同);而map,slice和function不能作为Key的类型。
Value :任何类型都可以。
对map进行并发访问时需增加同步机制
map在并发访问中使用不安全,因为不清楚当同时对map进行读写的时候会发生什么,如果像通过goroutine进行并发访问,则需要一种同步机制来保证访问数据的安全性。一种方式是使用sync.RWMutex
。
// 通过匿名结构体声明了一个变量counter,变量中包含了map和sync.RWMutex
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
// 读取数据的时候使用读锁
counter.RLock()
n := counter.m["Tony"]
counter.RUnlock()
// 写数据的使用使用写锁
counter.Lock()
counter.m["Tony"]++
counter.Unlock()