github.com/wangyougui/gf/v2@v2.6.5/container/gmap/gmap_hash_any_any_map.go (about) 1 // Copyright GoFrame Author(https://goframe.org). 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/wangyougui/gf. 6 7 package gmap 8 9 import ( 10 "github.com/wangyougui/gf/v2/container/gvar" 11 "github.com/wangyougui/gf/v2/internal/deepcopy" 12 "github.com/wangyougui/gf/v2/internal/empty" 13 "github.com/wangyougui/gf/v2/internal/json" 14 "github.com/wangyougui/gf/v2/internal/rwmutex" 15 "github.com/wangyougui/gf/v2/util/gconv" 16 "reflect" 17 ) 18 19 // AnyAnyMap wraps map type `map[interface{}]interface{}` and provides more map features. 20 type AnyAnyMap struct { 21 mu rwmutex.RWMutex 22 data map[interface{}]interface{} 23 } 24 25 // NewAnyAnyMap creates and returns an empty hash map. 26 // The parameter `safe` is used to specify whether using map in concurrent-safety, 27 // which is false in default. 28 func NewAnyAnyMap(safe ...bool) *AnyAnyMap { 29 return &AnyAnyMap{ 30 mu: rwmutex.Create(safe...), 31 data: make(map[interface{}]interface{}), 32 } 33 } 34 35 // NewAnyAnyMapFrom creates and returns a hash map from given map `data`. 36 // Note that, the param `data` map will be set as the underlying data map(no deep copy), 37 // there might be some concurrent-safe issues when changing the map outside. 38 func NewAnyAnyMapFrom(data map[interface{}]interface{}, safe ...bool) *AnyAnyMap { 39 return &AnyAnyMap{ 40 mu: rwmutex.Create(safe...), 41 data: data, 42 } 43 } 44 45 // Iterator iterates the hash map readonly with custom callback function `f`. 46 // If `f` returns true, then it continues iterating; or false to stop. 47 func (m *AnyAnyMap) Iterator(f func(k interface{}, v interface{}) bool) { 48 m.mu.RLock() 49 defer m.mu.RUnlock() 50 for k, v := range m.data { 51 if !f(k, v) { 52 break 53 } 54 } 55 } 56 57 // Clone returns a new hash map with copy of current map data. 58 func (m *AnyAnyMap) Clone(safe ...bool) *AnyAnyMap { 59 return NewFrom(m.MapCopy(), safe...) 60 } 61 62 // Map returns the underlying data map. 63 // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data, 64 // or else a pointer to the underlying data. 65 func (m *AnyAnyMap) Map() map[interface{}]interface{} { 66 m.mu.RLock() 67 defer m.mu.RUnlock() 68 if !m.mu.IsSafe() { 69 return m.data 70 } 71 data := make(map[interface{}]interface{}, len(m.data)) 72 for k, v := range m.data { 73 data[k] = v 74 } 75 return data 76 } 77 78 // MapCopy returns a shallow copy of the underlying data of the hash map. 79 func (m *AnyAnyMap) MapCopy() map[interface{}]interface{} { 80 m.mu.RLock() 81 defer m.mu.RUnlock() 82 data := make(map[interface{}]interface{}, len(m.data)) 83 for k, v := range m.data { 84 data[k] = v 85 } 86 return data 87 } 88 89 // MapStrAny returns a copy of the underlying data of the map as map[string]interface{}. 90 func (m *AnyAnyMap) MapStrAny() map[string]interface{} { 91 m.mu.RLock() 92 defer m.mu.RUnlock() 93 data := make(map[string]interface{}, len(m.data)) 94 for k, v := range m.data { 95 data[gconv.String(k)] = v 96 } 97 return data 98 } 99 100 // FilterEmpty deletes all key-value pair of which the value is empty. 101 // Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. 102 func (m *AnyAnyMap) FilterEmpty() { 103 m.mu.Lock() 104 defer m.mu.Unlock() 105 for k, v := range m.data { 106 if empty.IsEmpty(v) { 107 delete(m.data, k) 108 } 109 } 110 } 111 112 // FilterNil deletes all key-value pair of which the value is nil. 113 func (m *AnyAnyMap) FilterNil() { 114 m.mu.Lock() 115 defer m.mu.Unlock() 116 for k, v := range m.data { 117 if empty.IsNil(v) { 118 delete(m.data, k) 119 } 120 } 121 } 122 123 // Set sets key-value to the hash map. 124 func (m *AnyAnyMap) Set(key interface{}, value interface{}) { 125 m.mu.Lock() 126 if m.data == nil { 127 m.data = make(map[interface{}]interface{}) 128 } 129 m.data[key] = value 130 m.mu.Unlock() 131 } 132 133 // Sets batch sets key-values to the hash map. 134 func (m *AnyAnyMap) Sets(data map[interface{}]interface{}) { 135 m.mu.Lock() 136 if m.data == nil { 137 m.data = data 138 } else { 139 for k, v := range data { 140 m.data[k] = v 141 } 142 } 143 m.mu.Unlock() 144 } 145 146 // Search searches the map with given `key`. 147 // Second return parameter `found` is true if key was found, otherwise false. 148 func (m *AnyAnyMap) Search(key interface{}) (value interface{}, found bool) { 149 m.mu.RLock() 150 if m.data != nil { 151 value, found = m.data[key] 152 } 153 m.mu.RUnlock() 154 return 155 } 156 157 // Get returns the value by given `key`. 158 func (m *AnyAnyMap) Get(key interface{}) (value interface{}) { 159 m.mu.RLock() 160 if m.data != nil { 161 value = m.data[key] 162 } 163 m.mu.RUnlock() 164 return 165 } 166 167 // Pop retrieves and deletes an item from the map. 168 func (m *AnyAnyMap) Pop() (key, value interface{}) { 169 m.mu.Lock() 170 defer m.mu.Unlock() 171 for key, value = range m.data { 172 delete(m.data, key) 173 return 174 } 175 return 176 } 177 178 // Pops retrieves and deletes `size` items from the map. 179 // It returns all items if size == -1. 180 func (m *AnyAnyMap) Pops(size int) map[interface{}]interface{} { 181 m.mu.Lock() 182 defer m.mu.Unlock() 183 if size > len(m.data) || size == -1 { 184 size = len(m.data) 185 } 186 if size == 0 { 187 return nil 188 } 189 var ( 190 index = 0 191 newMap = make(map[interface{}]interface{}, size) 192 ) 193 for k, v := range m.data { 194 delete(m.data, k) 195 newMap[k] = v 196 index++ 197 if index == size { 198 break 199 } 200 } 201 return newMap 202 } 203 204 // doSetWithLockCheck checks whether value of the key exists with mutex.Lock, 205 // if not exists, set value to the map with given `key`, 206 // or else just return the existing value. 207 // 208 // When setting value, if `value` is type of `func() interface {}`, 209 // it will be executed with mutex.Lock of the hash map, 210 // and its return value will be set to the map with `key`. 211 // 212 // It returns value with given `key`. 213 func (m *AnyAnyMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} { 214 m.mu.Lock() 215 defer m.mu.Unlock() 216 if m.data == nil { 217 m.data = make(map[interface{}]interface{}) 218 } 219 if v, ok := m.data[key]; ok { 220 return v 221 } 222 if f, ok := value.(func() interface{}); ok { 223 value = f() 224 } 225 if value != nil { 226 m.data[key] = value 227 } 228 return value 229 } 230 231 // GetOrSet returns the value by key, 232 // or sets value with given `value` if it does not exist and then returns this value. 233 func (m *AnyAnyMap) GetOrSet(key interface{}, value interface{}) interface{} { 234 if v, ok := m.Search(key); !ok { 235 return m.doSetWithLockCheck(key, value) 236 } else { 237 return v 238 } 239 } 240 241 // GetOrSetFunc returns the value by key, 242 // or sets value with returned value of callback function `f` if it does not exist 243 // and then returns this value. 244 func (m *AnyAnyMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { 245 if v, ok := m.Search(key); !ok { 246 return m.doSetWithLockCheck(key, f()) 247 } else { 248 return v 249 } 250 } 251 252 // GetOrSetFuncLock returns the value by key, 253 // or sets value with returned value of callback function `f` if it does not exist 254 // and then returns this value. 255 // 256 // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` 257 // with mutex.Lock of the hash map. 258 func (m *AnyAnyMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { 259 if v, ok := m.Search(key); !ok { 260 return m.doSetWithLockCheck(key, f) 261 } else { 262 return v 263 } 264 } 265 266 // GetVar returns a Var with the value by given `key`. 267 // The returned Var is un-concurrent safe. 268 func (m *AnyAnyMap) GetVar(key interface{}) *gvar.Var { 269 return gvar.New(m.Get(key)) 270 } 271 272 // GetVarOrSet returns a Var with result from GetOrSet. 273 // The returned Var is un-concurrent safe. 274 func (m *AnyAnyMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { 275 return gvar.New(m.GetOrSet(key, value)) 276 } 277 278 // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. 279 // The returned Var is un-concurrent safe. 280 func (m *AnyAnyMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { 281 return gvar.New(m.GetOrSetFunc(key, f)) 282 } 283 284 // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. 285 // The returned Var is un-concurrent safe. 286 func (m *AnyAnyMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { 287 return gvar.New(m.GetOrSetFuncLock(key, f)) 288 } 289 290 // SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true. 291 // It returns false if `key` exists, and `value` would be ignored. 292 func (m *AnyAnyMap) SetIfNotExist(key interface{}, value interface{}) bool { 293 if !m.Contains(key) { 294 m.doSetWithLockCheck(key, value) 295 return true 296 } 297 return false 298 } 299 300 // SetIfNotExistFunc sets value with return value of callback function `f`, and then returns true. 301 // It returns false if `key` exists, and `value` would be ignored. 302 func (m *AnyAnyMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { 303 if !m.Contains(key) { 304 m.doSetWithLockCheck(key, f()) 305 return true 306 } 307 return false 308 } 309 310 // SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true. 311 // It returns false if `key` exists, and `value` would be ignored. 312 // 313 // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that 314 // it executes function `f` with mutex.Lock of the hash map. 315 func (m *AnyAnyMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { 316 if !m.Contains(key) { 317 m.doSetWithLockCheck(key, f) 318 return true 319 } 320 return false 321 } 322 323 // Remove deletes value from map by given `key`, and return this deleted value. 324 func (m *AnyAnyMap) Remove(key interface{}) (value interface{}) { 325 m.mu.Lock() 326 if m.data != nil { 327 var ok bool 328 if value, ok = m.data[key]; ok { 329 delete(m.data, key) 330 } 331 } 332 m.mu.Unlock() 333 return 334 } 335 336 // Removes batch deletes values of the map by keys. 337 func (m *AnyAnyMap) Removes(keys []interface{}) { 338 m.mu.Lock() 339 if m.data != nil { 340 for _, key := range keys { 341 delete(m.data, key) 342 } 343 } 344 m.mu.Unlock() 345 } 346 347 // Keys returns all keys of the map as a slice. 348 func (m *AnyAnyMap) Keys() []interface{} { 349 m.mu.RLock() 350 defer m.mu.RUnlock() 351 var ( 352 keys = make([]interface{}, len(m.data)) 353 index = 0 354 ) 355 for key := range m.data { 356 keys[index] = key 357 index++ 358 } 359 return keys 360 } 361 362 // Values returns all values of the map as a slice. 363 func (m *AnyAnyMap) Values() []interface{} { 364 m.mu.RLock() 365 defer m.mu.RUnlock() 366 var ( 367 values = make([]interface{}, len(m.data)) 368 index = 0 369 ) 370 for _, value := range m.data { 371 values[index] = value 372 index++ 373 } 374 return values 375 } 376 377 // Contains checks whether a key exists. 378 // It returns true if the `key` exists, or else false. 379 func (m *AnyAnyMap) Contains(key interface{}) bool { 380 var ok bool 381 m.mu.RLock() 382 if m.data != nil { 383 _, ok = m.data[key] 384 } 385 m.mu.RUnlock() 386 return ok 387 } 388 389 // Size returns the size of the map. 390 func (m *AnyAnyMap) Size() int { 391 m.mu.RLock() 392 length := len(m.data) 393 m.mu.RUnlock() 394 return length 395 } 396 397 // IsEmpty checks whether the map is empty. 398 // It returns true if map is empty, or else false. 399 func (m *AnyAnyMap) IsEmpty() bool { 400 return m.Size() == 0 401 } 402 403 // Clear deletes all data of the map, it will remake a new underlying data map. 404 func (m *AnyAnyMap) Clear() { 405 m.mu.Lock() 406 m.data = make(map[interface{}]interface{}) 407 m.mu.Unlock() 408 } 409 410 // Replace the data of the map with given `data`. 411 func (m *AnyAnyMap) Replace(data map[interface{}]interface{}) { 412 m.mu.Lock() 413 m.data = data 414 m.mu.Unlock() 415 } 416 417 // LockFunc locks writing with given callback function `f` within RWMutex.Lock. 418 func (m *AnyAnyMap) LockFunc(f func(m map[interface{}]interface{})) { 419 m.mu.Lock() 420 defer m.mu.Unlock() 421 f(m.data) 422 } 423 424 // RLockFunc locks reading with given callback function `f` within RWMutex.RLock. 425 func (m *AnyAnyMap) RLockFunc(f func(m map[interface{}]interface{})) { 426 m.mu.RLock() 427 defer m.mu.RUnlock() 428 f(m.data) 429 } 430 431 // Flip exchanges key-value of the map to value-key. 432 func (m *AnyAnyMap) Flip() { 433 m.mu.Lock() 434 defer m.mu.Unlock() 435 n := make(map[interface{}]interface{}, len(m.data)) 436 for k, v := range m.data { 437 n[v] = k 438 } 439 m.data = n 440 } 441 442 // Merge merges two hash maps. 443 // The `other` map will be merged into the map `m`. 444 func (m *AnyAnyMap) Merge(other *AnyAnyMap) { 445 m.mu.Lock() 446 defer m.mu.Unlock() 447 if m.data == nil { 448 m.data = other.MapCopy() 449 return 450 } 451 if other != m { 452 other.mu.RLock() 453 defer other.mu.RUnlock() 454 } 455 for k, v := range other.data { 456 m.data[k] = v 457 } 458 } 459 460 // String returns the map as a string. 461 func (m *AnyAnyMap) String() string { 462 if m == nil { 463 return "" 464 } 465 b, _ := m.MarshalJSON() 466 return string(b) 467 } 468 469 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 470 func (m AnyAnyMap) MarshalJSON() ([]byte, error) { 471 return json.Marshal(gconv.Map(m.Map())) 472 } 473 474 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 475 func (m *AnyAnyMap) UnmarshalJSON(b []byte) error { 476 m.mu.Lock() 477 defer m.mu.Unlock() 478 if m.data == nil { 479 m.data = make(map[interface{}]interface{}) 480 } 481 var data map[string]interface{} 482 if err := json.UnmarshalUseNumber(b, &data); err != nil { 483 return err 484 } 485 for k, v := range data { 486 m.data[k] = v 487 } 488 return nil 489 } 490 491 // UnmarshalValue is an interface implement which sets any type of value for map. 492 func (m *AnyAnyMap) UnmarshalValue(value interface{}) (err error) { 493 m.mu.Lock() 494 defer m.mu.Unlock() 495 if m.data == nil { 496 m.data = make(map[interface{}]interface{}) 497 } 498 for k, v := range gconv.Map(value) { 499 m.data[k] = v 500 } 501 return 502 } 503 504 // DeepCopy implements interface for deep copy of current type. 505 func (m *AnyAnyMap) DeepCopy() interface{} { 506 if m == nil { 507 return nil 508 } 509 510 m.mu.RLock() 511 defer m.mu.RUnlock() 512 data := make(map[interface{}]interface{}, len(m.data)) 513 for k, v := range m.data { 514 data[k] = deepcopy.Copy(v) 515 } 516 return NewFrom(data, m.mu.IsSafe()) 517 } 518 519 // IsSubOf checks whether the current map is a sub-map of `other`. 520 func (m *AnyAnyMap) IsSubOf(other *AnyAnyMap) bool { 521 if m == other { 522 return true 523 } 524 m.mu.RLock() 525 defer m.mu.RUnlock() 526 other.mu.RLock() 527 defer other.mu.RUnlock() 528 for key, value := range m.data { 529 otherValue, ok := other.data[key] 530 if !ok { 531 return false 532 } 533 if otherValue != value { 534 return false 535 } 536 } 537 return true 538 } 539 540 // Diff compares current map `m` with map `other` and returns their different keys. 541 // The returned `addedKeys` are the keys that are in map `m` but not in map `other`. 542 // The returned `removedKeys` are the keys that are in map `other` but not in map `m`. 543 // The returned `updatedKeys` are the keys that are both in map `m` and `other` but their values and not equal (`!=`). 544 func (m *AnyAnyMap) Diff(other *AnyAnyMap) (addedKeys, removedKeys, updatedKeys []interface{}) { 545 m.mu.RLock() 546 defer m.mu.RUnlock() 547 other.mu.RLock() 548 defer other.mu.RUnlock() 549 550 for key := range m.data { 551 if _, ok := other.data[key]; !ok { 552 removedKeys = append(removedKeys, key) 553 } else if !reflect.DeepEqual(m.data[key], other.data[key]) { 554 updatedKeys = append(updatedKeys, key) 555 } 556 } 557 for key := range other.data { 558 if _, ok := m.data[key]; !ok { 559 addedKeys = append(addedKeys, key) 560 } 561 } 562 return 563 }