github.com/zhongdalu/gf@v1.0.0/g/container/gmap/gmap_hash_int_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 8 package gmap 9 10 import ( 11 "encoding/json" 12 13 "github.com/zhongdalu/gf/g/container/gvar" 14 "github.com/zhongdalu/gf/g/internal/rwmutex" 15 "github.com/zhongdalu/gf/g/util/gconv" 16 ) 17 18 type IntAnyMap struct { 19 mu *rwmutex.RWMutex 20 data map[int]interface{} 21 } 22 23 // NewIntAnyMap returns an empty IntAnyMap object. 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 NewIntAnyMap(unsafe ...bool) *IntAnyMap { 27 return &IntAnyMap{ 28 mu: rwmutex.New(unsafe...), 29 data: make(map[int]interface{}), 30 } 31 } 32 33 // NewIntAnyMapFrom 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 NewIntAnyMapFrom(data map[int]interface{}, unsafe ...bool) *IntAnyMap { 37 return &IntAnyMap{ 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 *IntAnyMap) Iterator(f func(k int, 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 *IntAnyMap) Clone() *IntAnyMap { 57 return NewIntAnyMapFrom(m.Map(), !m.mu.IsSafe()) 58 } 59 60 // Map returns a copy of the data of the hash map. 61 func (m *IntAnyMap) Map() map[int]interface{} { 62 m.mu.RLock() 63 data := make(map[int]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 *IntAnyMap) Set(key int, 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 *IntAnyMap) Sets(data map[int]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 *IntAnyMap) Search(key int) (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 *IntAnyMap) Get(key int) 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 *IntAnyMap) doSetWithLockCheck(key int, 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 if value != nil { 123 m.data[key] = value 124 } 125 return value 126 } 127 128 // GetOrSet returns the value by key, 129 // or set value with given <value> if not exist and returns this value. 130 func (m *IntAnyMap) GetOrSet(key int, value interface{}) interface{} { 131 if v, ok := m.Search(key); !ok { 132 return m.doSetWithLockCheck(key, value) 133 } else { 134 return v 135 } 136 } 137 138 // GetOrSetFunc returns the value by key, 139 // or sets value with return value of callback function <f> if not exist and returns this value. 140 func (m *IntAnyMap) GetOrSetFunc(key int, f func() interface{}) interface{} { 141 if v, ok := m.Search(key); !ok { 142 return m.doSetWithLockCheck(key, f()) 143 } else { 144 return v 145 } 146 } 147 148 // GetOrSetFuncLock returns the value by key, 149 // or sets value with return value of callback function <f> if not exist 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 *IntAnyMap) GetOrSetFuncLock(key int, 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 *IntAnyMap) GetVar(key int) *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 *IntAnyMap) GetVarOrSet(key int, 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 *IntAnyMap) GetVarOrSetFunc(key int, 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 *IntAnyMap) GetVarOrSetFuncLock(key int, 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 *IntAnyMap) SetIfNotExist(key int, 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 *IntAnyMap) SetIfNotExistFunc(key int, 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 *IntAnyMap) SetIfNotExistFuncLock(key int, f func() interface{}) bool { 211 if !m.Contains(key) { 212 m.doSetWithLockCheck(key, f) 213 return true 214 } 215 return false 216 } 217 218 // Removes batch deletes values of the map by keys. 219 func (m *IntAnyMap) Removes(keys []int) { 220 m.mu.Lock() 221 for _, key := range keys { 222 delete(m.data, key) 223 } 224 m.mu.Unlock() 225 } 226 227 // Remove deletes value from map by given <key>, and return this deleted value. 228 func (m *IntAnyMap) Remove(key int) interface{} { 229 m.mu.Lock() 230 val, exists := m.data[key] 231 if exists { 232 delete(m.data, key) 233 } 234 m.mu.Unlock() 235 return val 236 } 237 238 // Keys returns all keys of the map as a slice. 239 func (m *IntAnyMap) Keys() []int { 240 m.mu.RLock() 241 keys := make([]int, 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 *IntAnyMap) 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 *IntAnyMap) Contains(key int) 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 *IntAnyMap) 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 *IntAnyMap) 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 *IntAnyMap) Clear() { 292 m.mu.Lock() 293 m.data = make(map[int]interface{}) 294 m.mu.Unlock() 295 } 296 297 // LockFunc locks writing with given callback function <f> within RWMutex.Lock. 298 func (m *IntAnyMap) LockFunc(f func(m map[int]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 *IntAnyMap) RLockFunc(f func(m map[int]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 *IntAnyMap) Flip() { 313 m.mu.Lock() 314 defer m.mu.Unlock() 315 n := make(map[int]interface{}, len(m.data)) 316 for k, v := range m.data { 317 n[gconv.Int(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 *IntAnyMap) Merge(other *IntAnyMap) { 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 *IntAnyMap) MarshalJSON() ([]byte, error) { 338 m.mu.RLock() 339 defer m.mu.RUnlock() 340 return json.Marshal(m.data) 341 }