【Go夯实基础】sync.Map的缺陷与解决方法

1、存在的问题

  • 为了考虑通用性,所有的key和value都是interface{},换言之,我们失去了类型检查提供的安全性而且被迫更多的使用类型断言,后果:
    • 在每次调用API后都小心翼翼地使用类型断言,你的代码里面出现无数的if v,ok=value.(xxType);!ok{}

2、解决方案

2.1 方案一

  • 如果有明确类型,一个简单的思路是封装snyc.Map,外部函数限制传给sync.Map的API的参数类型,但是灵活性较差
type StringMap struct{
    m sync.Map
}
func (s *StringMap) Store(key,value string){
    s.m.Store(key,value)
}
func (s *StringMap) Load(key string)(value string,ok bool){
    v, ok := s.m.Load(key)
    if v != nil {
        value = v.(string)
    }
    return
}
复制代码

2.2 方案二

  • 用反射来帮助我们做类型检查(下面的代码来自于极客时间《go核心36讲》附属源代码)
type ConcurrentMap struct {
	m         sync.Map
	keyType   reflect.Type
	valueType reflect.Type
}

//创建ConcurrentMap
func NewConcurrentMap(keyType, valueType reflect.Type) (*ConcurrentMap, error) {
	if keyType == nil {
		return nil, errors.New("nil key type")
	}
	if !keyType.Comparable() {
		return nil, fmt.Errorf("incomparable key type: %s", keyType)
	}
	if valueType == nil {
		return nil, errors.New("nil value type")
	}
	cMap := &ConcurrentMap{
		keyType:   keyType,
		valueType: valueType,
	}
	return cMap, nil
}

func (cMap *ConcurrentMap) Delete(key interface{}) {
        //传入的参数类型必须要和 初始化的ConcurrentMap的key类型一致
	if reflect.TypeOf(key) != cMap.keyType {
		return
	}
	cMap.m.Delete(key)
}
复制代码

猜你喜欢

转载自juejin.im/post/7031471153067589646
今日推荐