Go-并发安全字典

Go-并发安全字典,第1张

sync.Map 一个 read 字典, 一个 dirty 字典read 的键值对不一定全, dirty 的总是完全的(不包括被删除的键值对)适合读多写少的场景性能影响从大到小: 新增, 删除, 修改 自己定义结构体, 明确键值类型通过反射实现一个统一的类型

上代码, 自己品:

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var i int
	var list []string

	fmt.Println("int comparable: ", reflect.TypeOf(i).Comparable())      // true
	fmt.Println("slice comparable: ", reflect.TypeOf(list).Comparable()) // false

}
package main

import (
	"sync"
)

type IntStrMap struct {
	// m 不对外暴露, 所以只能使用 IntStrMap, 其成员方法都有明确的类型, 可以规律类型的问题
	m sync.Map
}

func (self *IntStrMap) Delete(key int) {
	self.m.Delete(key)
}

func (self *IntStrMap) Load(key int) (value string, ok bool) {
	v, ok := self.m.Load(key)
	if v != nil {
		value = v.(string)
	}
	return
}

func (self *IntStrMap) LoadOrStore(key int, value string) (actual string, loaded bool) {
	a, loaded := self.m.LoadOrStore(key, value)
	actual = a.(string)
	return
}

func (self *IntStrMap) Store(key int, value string) {
	self.m.Store(key, value)
}

func (self *IntStrMap) Range(f func(key int, value string) bool) {
	self.m.Range(func(key, value interface{}) bool {
		return f(key.(int), value.(string))
	})
}
package main

import (
	"fmt"
	"reflect"
	"sync"
)

type ConcurrentMap struct {
	m         sync.Map
	keyType   reflect.Type
	valueType reflect.Type
}

func (self *ConcurrentMap) checkKeyType(key interface{}) (keyType reflect.Type, ok bool) {
	if self.keyType == nil {
		ok = true
		return
	}
	keyType = reflect.TypeOf(key)
	ok = keyType == self.keyType
	return
}

func (self *ConcurrentMap) checkValueType(value interface{}) (valueType reflect.Type, ok bool) {
	if self.valueType == nil {
		ok = true
		return
	}
	valueType = reflect.TypeOf(value)
	ok = valueType == self.valueType
	return
}

func (self *ConcurrentMap) checkStore(key interface{}, value interface{}) {
	// 不一定非要引发 panic, 也可以增加返回值来告知调用方, 或者在结构体定义一个字段
	if self.keyType == nil {
		keyType := reflect.TypeOf(key)
		if !keyType.Comparable() {
			panic(fmt.Errorf("错误的 key 类型: %v", keyType))
		}
		self.keyType = keyType
	} else if keyType, ok := self.checkKeyType(key); !ok {
		panic(fmt.Errorf("错误的 key 类型: %v", keyType))
	}

	if self.valueType == nil {
		self.valueType = reflect.TypeOf(value)
	} else if valueType, ok := self.checkValueType(value); !ok {
		panic(fmt.Errorf("错误的 value 类型: %v", valueType))
	}
}

func (self *ConcurrentMap) Delete(key interface{}) {
	if keyType, ok := self.checkKeyType(key); !ok {
		panic(fmt.Errorf("错误的 key 类型: %v", keyType))
	}
	self.m.Delete(key)
}

func (self *ConcurrentMap) Load(key interface{}) (value interface{}, ok bool) {
	if _, ok = self.checkKeyType(key); !ok {
		return
	}
	return self.m.Load(key)
}

func (self *ConcurrentMap) LoadOrStore(key interface{}, value interface{}) (actual interface{}, loaded bool) {
	self.checkStore(key, value)
	return self.m.LoadOrStore(key, value)
}

func (self *ConcurrentMap) Store(key interface{}, value interface{}) {
	self.checkStore(key, value)
	self.m.Store(key, value)
}

func (self *ConcurrentMap) Range(f func(key interface{}, value interface{}) bool) {
	self.m.Range(f)
}

func main() {
	cmap := ConcurrentMap{}

	cmap.Delete(3)

	cmap.Load("abc")

	fmt.Println(cmap.keyType, cmap.valueType) //  

	actual, loaded := cmap.LoadOrStore(3, "abc-efg")
	fmt.Println("actual: ", actual) // abc-efg
	fmt.Println("loaded: ", loaded) // false

	fmt.Println(cmap.keyType, cmap.valueType) // int string

	cmap.Store(3, "abc")

	value, ok := cmap.Load(3)
	fmt.Println("value: ", value) // abc
	fmt.Println("ok: ", ok)       // true

	actual, loaded = cmap.LoadOrStore(3, "efg")
	fmt.Println("actual: ", actual) // abc
	fmt.Println("loaded: ", loaded) // true

	value, ok = cmap.Load("abc")
	fmt.Println("value: ", value) // 
	fmt.Println("ok: ", ok)       // false

	cmap.Delete("abc") // panic: 错误的 key 类型: string

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994256.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存