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