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