github.com/godaddy-x/freego@v1.0.156/utils/concurrent/map.go (about) 1 package concurrent 2 3 import ( 4 "errors" 5 "sync" 6 ) 7 8 type Map struct { 9 lock sync.RWMutex 10 data map[string]interface{} 11 } 12 13 func NewMap() *Map { 14 return &Map{data: map[string]interface{}{}} 15 } 16 17 func (self *Map) Get(key string, callfun func(key string) (interface{}, error)) (interface{}, error) { 18 if len(key) == 0 { 19 return nil, errors.New("get key is nil") 20 } 21 if callfun == nil { 22 return nil, errors.New("get callfun is nil") 23 } 24 var b bool 25 var v interface{} 26 var err error 27 //self.lock.RLock() 28 if v, b = self.data[key]; !b { 29 //self.lock.RUnlock() 30 self.lock.Lock() 31 if v, b = self.data[key]; !b { 32 v, err = callfun(key) 33 if v != nil && err == nil { 34 self.data[key] = v 35 } 36 } 37 self.lock.Unlock() 38 } else { 39 //self.lock.RUnlock() 40 } 41 return v, err 42 } 43 44 func (self *Map) Del(key string, callfun func(key string) (interface{}, error)) error { 45 var b bool 46 var err error 47 self.lock.RLock() 48 if _, b = self.data[key]; b { 49 self.lock.RUnlock() 50 self.lock.Lock() 51 if _, b = self.data[key]; b { 52 if callfun != nil { 53 _, err = callfun(key) 54 } 55 if err == nil { 56 delete(self.data, key) 57 } 58 } 59 self.lock.Unlock() 60 } else { 61 self.lock.RUnlock() 62 } 63 return err 64 } 65 66 func (self *Map) Set(key string, callfun func(key string) (interface{}, error)) (interface{}, error) { 67 if len(key) == 0 { 68 return nil, errors.New("set key is nil") 69 } 70 if callfun == nil { 71 return nil, errors.New("set callfun is nil") 72 } 73 self.lock.Lock() 74 v, err := callfun(key) 75 if v != nil && err == nil { 76 self.data[key] = v 77 } 78 self.lock.Unlock() 79 return v, err 80 }