线程安全的Map
Go内建的Map
Go内建的Map类型:Map[K]V
K必须是可比较类型,V可以是任意类型也可以是nil
在Go中整数、浮点数、复数、string、chan、指针、接口、包含可比较元素的struct和数组都是可比较类型,slice、map、func不是可比较类型
注意:使用包含可比较元素的struct当做key时,如果struct的可比较元素值改变了那么无法根据这个struct获取到对应的value
import "fmt"
type structKey struct {
a int32
}
func testStructKey() {
var key structKey
key.a = 1
m := make(map[structKey]string)
m[key] = "hello"
fmt.Printf("init value is :%v\n", m[key])
key.a = 2
fmt.Printf("key change value is: %v\n", m[key])
}
在Go中,map[K]可以返回一个值也可以返回两个值,因为当K不存在时会返回零值,但这个零值是本身就设置的零值还是由于K不存在返回的,就需要根据第二个返回值判断,第二个返回值是False说明是因为K不存在,第二个返回值是True说明K存在是本身设置的零值
Map是无序的,当遍历一个Map的时候,迭代元素的顺序不确定
如果想要保证元素有序,比如按照插入顺序排序,那么可以使用orderedMap
orderedMap: https://github.com/elliotchance/orderedmap
Map常见错误
未初始化
Map在使用前一定要初始化
未初始化的Map直接赋值会导致panic,取值不会panic会取到零值
并发读写
Go内建的Map不是并发安全的,Go的runtime会检测Map是否存在并发读写,如果存在那么会panic
实现并发安全的Map
直接加读写锁
源码实现
type RWMutexMap struct {
rMu sync.RWMutex
m map[interface{}]interface{}
}
func (m *RWMutexMap) Store(key interface{}, value interface{}) {
m.rMu.Lock()
defer m.rMu.Unlock()
m.m[key] = value
}
func (m *RWMutexMap) Load(key interface{}) (interface{}, bool) {
m.rMu.RLock()
defer m.rMu.RUnlock()
value, ok := m.m[key]
return value, ok
}
func (m *RWMutexMap) Delete(key interface{}) {
m.rMu.Lock()
defer m.rMu.Unlock()
delete(m.m, key)
}
func (m *RWMutexMap) Len() int {
m.rMu.RLock()
defer m.rMu.RUnlock()
return len(m.m)
}
func (m *RWMutexMap) Each(f func(key interface{}, value interface{}) error) error {
m.rMu.RLock()
defer m.rMu.RUnlock()
for key, value := range m.m {
err := f(key, value)
if err