github.com/zhongdalu/gf@v1.0.0/g/container/gmap/gmap_hash_any_any_map.go (about) 1 // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with gm file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package gmap 8 9 import ( 10 "encoding/json" 11 12 "github.com/zhongdalu/gf/g/util/gconv" 13 14 "github.com/zhongdalu/gf/g/container/gvar" 15 "github.com/zhongdalu/gf/g/internal/rwmutex" 16 ) 17 18 type AnyAnyMap struct { 19 mu *rwmutex.RWMutex 20 data map[interface{}]interface{} 21 } 22 23 // NewAnyAnyMap returns an empty hash map. 24 // The parameter <unsafe> used to specify whether using map in un-concurrent-safety, 25 // which is false in default, means concurrent-safe. 26 func NewAnyAnyMap(unsafe ...bool) *AnyAnyMap { 27 return &AnyAnyMap{ 28 mu: rwmutex.New(unsafe...), 29 data: make(map[interface{}]interface{}), 30 } 31 } 32 33 // NewAnyAnyMapFrom returns a hash map from given map <data>. 34 // Note that, the param <data> map will be set as the underlying data map(no deep copy), 35 // there might be some concurrent-safe issues when changing the map outside. 36 func NewAnyAnyMapFrom(data map[interface{}]interface{}, unsafe ...bool) *AnyAnyMap { 37 return &AnyAnyMap{ 38 mu: rwmutex.New(unsafe...), 39 data: data, 40 } 41 } 42 43 // Iterator iterates the hash map with custom callback function <f>. 44 // If <f> returns true, then it continues iterating; or false to stop. 45 func (m *AnyAnyMap) Iterator(f func(k interface{}, v interface{}) bool) { 46 m.mu.RLock() 47 defer m.mu.RUnlock() 48 for k, v := range m.data { 49 if !f(k, v) { 50 break 51 } 52 } 53 } 54 55 // Clone returns a new hash map with copy of current map data. 56 func (m *AnyAnyMap) Clone(unsafe ...bool) *AnyAnyMap { 57 return NewFrom(m.Map(), unsafe...) 58 } 59 60 // Map returns a copy of the data of the hash map. 61 func (m *AnyAnyMap) Map() map[interface{}]interface{} { 62 m.mu.RLock() 63 data := make(map[interface{}]interface{}, len(m.data)) 64 for k, v := range m.data { 65 data[k] = v 66 } 67 m.mu.RUnlock() 68 return data 69 } 70 71 // Set sets key-value to the hash map. 72 func (m *AnyAnyMap) Set(key interface{}, val interface{}) { 73 m.mu.Lock() 74 m.data[key] = val 75 m.mu.Unlock() 76 } 77 78 // Sets batch sets key-values to the hash map. 79 func (m *AnyAnyMap) Sets(data map[interface{}]interface{}) { 80 m.mu.Lock() 81 for k, v := range data { 82 m.data[k] = v 83 } 84 m.mu.Unlock() 85 } 86 87 // Search searches the map with given <key>. 88 // Second return parameter <found> is true if key was found, otherwise false. 89 func (m *AnyAnyMap) Search(key interface{}) (value interface{}, found bool) { 90 m.mu.RLock() 91 value, found = m.data[key] 92 m.mu.RUnlock() 93 return 94 } 95 96 // Get returns the value by given <key>. 97 func (m *AnyAnyMap) Get(key interface{}) interface{} { 98 m.mu.RLock() 99 val, _ := m.data[key] 100 m.mu.RUnlock() 101 return val 102 } 103 104 // doSetWithLockCheck checks whether value of the key exists with mutex.Lock, 105 // if not exists, set value to the map with given <key>, 106 // or else just return the existing value. 107 // 108 // When setting value, if <value> is type of <func() interface {}>, 109 // it will be executed with mutex.Lock of the hash map, 110 // and its return value will be set to the map with <key>. 111 // 112 // It returns value with given <key>. 113 func (m *AnyAnyMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} { 114 m.mu.Lock() 115 defer m.mu.Unlock() 116 if v, ok := m.data[key]; ok { 117 return v 118 } 119 if f, ok := value.(func() interface{}); ok { 120 value = f() 121 } 122 m.data[key] = value 123 return value 124 } 125 126 // GetOrSet returns the value by key, 127 // or set value with given <value> if not exist and returns this value. 128 func (m *AnyAnyMap) GetOrSet(key interface{}, value interface{}) interface{} { 129 if v, ok := m.Search(key); !ok { 130 return m.doSetWithLockCheck(key, value) 131 } else { 132 return v 133 } 134 } 135 136 // GetOrSetFunc returns the value by key, 137 // or sets value with return value of callback function <f> if not exist 138 // and returns this value. 139 func (m *AnyAnyMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { 140 if v, ok := m.Search(key); !ok { 141 return m.doSetWithLockCheck(key, f()) 142 } else { 143 return v 144 } 145 } 146 147 // GetOrSetFuncLock returns the value by key, 148 // or sets value with return value of callback function <f> if not exist 149 // and returns this value. 150 // 151 // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f> 152 // with mutex.Lock of the hash map. 153 func (m *AnyAnyMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { 154 if v, ok := m.Search(key); !ok { 155 return m.doSetWithLockCheck(key, f) 156 } else { 157 return v 158 } 159 } 160 161 // GetVar returns a gvar.Var with the value by given <key>. 162 // The returned gvar.Var is un-concurrent safe. 163 func (m *AnyAnyMap) GetVar(key interface{}) *gvar.Var { 164 return gvar.New(m.Get(key), true) 165 } 166 167 // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. 168 // The returned gvar.Var is un-concurrent safe. 169 func (m *AnyAnyMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { 170 return gvar.New(m.GetOrSet(key, value), true) 171 } 172 173 // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. 174 // The returned gvar.Var is un-concurrent safe. 175 func (m *AnyAnyMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { 176 return gvar.New(m.GetOrSetFunc(key, f), true) 177 } 178 179 // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. 180 // The returned gvar.Var is un-concurrent safe. 181 func (m *AnyAnyMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { 182 return gvar.New(m.GetOrSetFuncLock(key, f), true) 183 } 184 185 // SetIfNotExist sets <value> to the map if the <key> does not exist, then return true. 186 // It returns false if <key> exists, and <value> would be ignored. 187 func (m *AnyAnyMap) SetIfNotExist(key interface{}, value interface{}) bool { 188 if !m.Contains(key) { 189 m.doSetWithLockCheck(key, value) 190 return true 191 } 192 return false 193 } 194 195 // SetIfNotExistFunc sets value with return value of callback function <f>, then return true. 196 // It returns false if <key> exists, and <value> would be ignored. 197 func (m *AnyAnyMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { 198 if !m.Contains(key) { 199 m.doSetWithLockCheck(key, f()) 200 return true 201 } 202 return false 203 } 204 205 // SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true. 206 // It returns false if <key> exists, and <value> would be ignored. 207 // 208 // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that 209 // it executes function <f> with mutex.Lock of the hash map. 210 func (m *AnyAnyMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { 211 if !m.Contains(key) { 212 m.doSetWithLockCheck(key, f) 213 return true 214 } 215 return false 216 } 217 218 // Remove deletes value from map by given <key>, and return this deleted value. 219 func (m *AnyAnyMap) Remove(key interface{}) interface{} { 220 m.mu.Lock() 221 val, exists := m.data[key] 222 if exists { 223 delete(m.data, key) 224 } 225 m.mu.Unlock() 226 return val 227 } 228 229 // Removes batch deletes values of the map by keys. 230 func (m *AnyAnyMap) Removes(keys []interface{}) { 231 m.mu.Lock() 232 for _, key := range keys { 233 delete(m.data, key) 234 } 235 m.mu.Unlock() 236 } 237 238 // Keys returns all keys of the map as a slice. 239 func (m *AnyAnyMap) Keys() []interface{} { 240 m.mu.RLock() 241 keys := make([]interface{}, len(m.data)) 242 index := 0 243 for key := range m.data { 244 keys[index] = key 245 index++ 246 } 247 m.mu.RUnlock() 248 return keys 249 } 250 251 // Values returns all values of the map as a slice. 252 func (m *AnyAnyMap) Values() []interface{} { 253 m.mu.RLock() 254 values := make([]interface{}, len(m.data)) 255 index := 0 256 for _, value := range m.data { 257 values[index] = value 258 index++ 259 } 260 m.mu.RUnlock() 261 return values 262 } 263 264 // Contains checks whether a key exists. 265 // It returns true if the <key> exists, or else false. 266 func (m *AnyAnyMap) Contains(key interface{}) bool { 267 m.mu.RLock() 268 _, exists := m.data[key] 269 m.mu.RUnlock() 270 return exists 271 } 272 273 // Size returns the size of the map. 274 func (m *AnyAnyMap) Size() int { 275 m.mu.RLock() 276 length := len(m.data) 277 m.mu.RUnlock() 278 return length 279 } 280 281 // IsEmpty checks whether the map is empty. 282 // It returns true if map is empty, or else false. 283 func (m *AnyAnyMap) IsEmpty() bool { 284 m.mu.RLock() 285 empty := len(m.data) == 0 286 m.mu.RUnlock() 287 return empty 288 } 289 290 // Clear deletes all data of the map, it will remake a new underlying data map. 291 func (m *AnyAnyMap) Clear() { 292 m.mu.Lock() 293 m.data = make(map[interface{}]interface{}) 294 m.mu.Unlock() 295 } 296 297 // LockFunc locks writing with given callback function <f> within RWMutex.Lock. 298 func (m *AnyAnyMap) LockFunc(f func(m map[interface{}]interface{})) { 299 m.mu.Lock() 300 defer m.mu.Unlock() 301 f(m.data) 302 } 303 304 // RLockFunc locks reading with given callback function <f> within RWMutex.RLock. 305 func (m *AnyAnyMap) RLockFunc(f func(m map[interface{}]interface{})) { 306 m.mu.RLock() 307 defer m.mu.RUnlock() 308 f(m.data) 309 } 310 311 // Flip exchanges key-value of the map to value-key. 312 func (m *AnyAnyMap) Flip() { 313 m.mu.Lock() 314 defer m.mu.Unlock() 315 n := make(map[interface{}]interface{}, len(m.data)) 316 for k, v := range m.data { 317 n[v] = k 318 } 319 m.data = n 320 } 321 322 // Merge merges two hash maps. 323 // The <other> map will be merged into the map <m>. 324 func (m *AnyAnyMap) Merge(other *AnyAnyMap) { 325 m.mu.Lock() 326 defer m.mu.Unlock() 327 if other != m { 328 other.mu.RLock() 329 defer other.mu.RUnlock() 330 } 331 for k, v := range other.data { 332 m.data[k] = v 333 } 334 } 335 336 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 337 func (m *AnyAnyMap) MarshalJSON() ([]byte, error) { 338 return json.Marshal(gconv.Map(m.Map())) 339 }