Skip to content

Commit

Permalink
重构字典的实现,改用sync.Map
Browse files Browse the repository at this point in the history
  • Loading branch information
steden committed Oct 10, 2024
1 parent a163f7b commit 2ba80a4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 104 deletions.
55 changes: 13 additions & 42 deletions dictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,45 +35,30 @@ func (receiver *Dictionary[TKey, TValue]) AddMap(source map[TKey]TValue) {

// Add 添加元素
func (receiver *Dictionary[TKey, TValue]) Add(key TKey, value TValue) {
receiver.lock.Lock()
defer receiver.lock.Unlock()

receiver.source[key] = value
receiver.source.Store(key, value)
}

// Update 更新元素
func (receiver *Dictionary[TKey, TValue]) Update(key TKey, f func(value *TValue)) {
receiver.lock.Lock()
defer receiver.lock.Unlock()

v := receiver.source[key]
f(&v)
receiver.source[key] = v
v, _ := receiver.source.Load(key)
v2 := v.(TValue)
f(&v2)
receiver.source.Store(key, v2)
}

// Clear 清除元素
func (receiver *Dictionary[TKey, TValue]) Clear() {
receiver.lock.Lock()
defer receiver.lock.Unlock()

receiver.source = make(map[TKey]TValue)
receiver.source = &sync.Map{}
}

// Remove 移除元素
func (receiver *Dictionary[TKey, TValue]) Remove(key TKey) {
receiver.lock.Lock()
defer receiver.lock.Unlock()

delete(receiver.source, key)
receiver.source.Delete(key)
}

// Scan scan value into Jsonb, implements sql.Scanner interface
func (receiver *Dictionary[TKey, TValue]) Scan(val any) error {
if val == nil {
if receiver.lock != nil {
receiver.lock.Lock()
defer receiver.lock.Unlock()
}
*receiver = NewDictionary[TKey, TValue]()
return nil
}
Expand All @@ -93,43 +78,29 @@ func (receiver *Dictionary[TKey, TValue]) Scan(val any) error {
func (receiver *Dictionary[TKey, TValue]) UnmarshalJSON(ba []byte) error {
t := map[TKey]TValue{}
err := json.Unmarshal(ba, &t)

if receiver.lock != nil {
receiver.lock.Lock()
defer receiver.lock.Unlock()
}

*receiver = NewDictionaryFromMap(t)
return err
}

// ToReadonlyDictionary 转成ReadonlyDictionary对象
func (receiver *Dictionary[TKey, TValue]) ToReadonlyDictionary() ReadonlyDictionary[TKey, TValue] {
receiver.lock.RLock()
defer receiver.lock.RUnlock()

return receiver.ReadonlyDictionary
}

// New 初始化(用于反映时使用)
func (receiver *Dictionary[TKey, TValue]) New() {
if receiver.source == nil {
var lock sync.RWMutex
receiver.source = make(map[TKey]TValue)
receiver.lock = &lock
receiver.source = &sync.Map{}
}
}

// Foreach for range操作
func (receiver *Dictionary[TKey, TValue]) Foreach(itemFn func(TKey, TValue)) {
if receiver.lock == nil {
if receiver.source == nil {
return
}

receiver.lock.RLock()
defer receiver.lock.RUnlock()

for k, v := range receiver.source {
itemFn(k, v)
}
receiver.source.Range(func(key, value any) bool {
itemFn(key.(TKey), value.(TValue))
return true
})
}
115 changes: 53 additions & 62 deletions readonlyDictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,120 +10,119 @@ import (
// ReadonlyDictionary 只读字典
type ReadonlyDictionary[TKey comparable, TValue any] struct {
// source array
source map[TKey]TValue
lock *sync.RWMutex
source *sync.Map
}

// NewReadonlyDictionary 创建一个字典
func NewReadonlyDictionary[TKey comparable, TValue any]() ReadonlyDictionary[TKey, TValue] {
return ReadonlyDictionary[TKey, TValue]{
source: make(map[TKey]TValue),
lock: &sync.RWMutex{},
source: &sync.Map{},
}
}

// NewReadonlyDictionaryFromMap 创建一个字典
func NewReadonlyDictionaryFromMap[TKey comparable, TValue any](source map[TKey]TValue) ReadonlyDictionary[TKey, TValue] {
if source == nil {
source = make(map[TKey]TValue)
rdc := ReadonlyDictionary[TKey, TValue]{
source: &sync.Map{},
}
return ReadonlyDictionary[TKey, TValue]{
source: source,
lock: &sync.RWMutex{},
for key, value := range source {
rdc.source.Store(key, value)
}
return rdc
}

// Values 获取字典的value
func (receiver ReadonlyDictionary[TKey, TValue]) Values() List[TValue] {
if receiver.lock==nil{
if receiver.source == nil {
return NewList[TValue]()
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

lst := NewList[TValue]()
for _, v := range receiver.source {
lst.Add(v)
}
receiver.source.Range(func(key, value any) bool {
lst.Add(value.(TValue))
return true
})
return lst
}

// Keys 获取字典的Keys
func (receiver ReadonlyDictionary[TKey, TValue]) Keys() List[TKey] {
if receiver.lock==nil{
if receiver.source == nil {
return NewList[TKey]()
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

lst := NewList[TKey]()
for k := range receiver.source {
lst.Add(k)
}
receiver.source.Range(func(key, value any) bool {
lst.Add(key.(TKey))
return true
})
return lst
}

// Count 获取字典数量
func (receiver ReadonlyDictionary[TKey, TValue]) Count() int {
if receiver.lock == nil {
if receiver.source == nil {
return 0
}

receiver.lock.RLock()
defer receiver.lock.RUnlock()

return len(receiver.source)
count := 0
receiver.source.Range(func(key, value any) bool {
count++
return true
})
return count
}

// ContainsKey 是否存在KEY
func (receiver ReadonlyDictionary[TKey, TValue]) ContainsKey(key TKey) bool {
if receiver.lock==nil{
if receiver.source == nil {
return false
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

_, exists := receiver.source[key]
_, exists := receiver.source.Load(key)
return exists
}

// ContainsValue 是否存在指定的Value
func (receiver ReadonlyDictionary[TKey, TValue]) ContainsValue(value TValue) bool {
if receiver.lock==nil{
func (receiver ReadonlyDictionary[TKey, TValue]) ContainsValue(v TValue) bool {
if receiver.source == nil {
return false
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

for _, itemValue := range receiver.source {
if parse.IsEqual(value, itemValue) {
return true
}
}
return false
result := false
receiver.source.Range(func(key, value any) bool {
result = parse.IsEqual(v, value.(TValue))
return !result
})
return result
}

// GetValue 获取指定KEY的Value
func (receiver ReadonlyDictionary[TKey, TValue]) GetValue(key TKey) TValue {
if receiver.lock==nil{
if receiver.source == nil {
var val TValue
return val
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

return receiver.source[key]
if v, exists := receiver.source.Load(key); exists {
return v.(TValue)
}

var val TValue
return val
}

// ToMap 转成map对象
func (receiver ReadonlyDictionary[TKey, TValue]) ToMap() map[TKey]TValue {
if receiver.lock==nil{
if receiver.source == nil {
return make(map[TKey]TValue)
}
receiver.lock.RLock()
defer receiver.lock.RUnlock()

return receiver.source
m := make(map[TKey]TValue)
receiver.source.Range(func(key, value any) bool {
m[key.(TKey)] = value.(TValue)
return true
})
return m
}

// Value return json value, implement driver.Valuer interface
Expand All @@ -138,14 +137,11 @@ func (receiver ReadonlyDictionary[TKey, TValue]) Value() (driver.Value, error) {
// MarshalJSON to output non base64 encoded []byte
// 此处不能用指针,否则json序列化时不执行
func (receiver ReadonlyDictionary[TKey, TValue]) MarshalJSON() ([]byte, error) {
if receiver.source == nil || receiver.lock == nil {
if receiver.source == nil {
return []byte("{}"), nil
}

receiver.lock.RLock()
defer receiver.lock.RUnlock()

return json.Marshal(receiver.source)
return json.Marshal(receiver.ToMap())
}

// GormDataType gorm common data type
Expand All @@ -155,19 +151,14 @@ func (receiver ReadonlyDictionary[TKey, TValue]) GormDataType() string {

// IsNil 是否未初始化
func (receiver ReadonlyDictionary[TKey, TValue]) IsNil() bool {
if receiver.lock == nil {
return true
}

receiver.lock.RLock()
defer receiver.lock.RUnlock()

return receiver.source == nil
}

// ToDictionary 返回只写字典
func (receiver ReadonlyDictionary[TKey, TValue]) ToDictionary() Dictionary[TKey, TValue] {
return NewDictionaryFromMap(receiver.source)
return Dictionary[TKey, TValue]{
ReadonlyDictionary: receiver,
}
}

//// GormDBDataType gorm db data type
Expand Down

0 comments on commit 2ba80a4

Please sign in to comment.