Skip to content

Commit 7474b45

Browse files
authored
fix(container/gmap): added WithError methods for KVMap and ListKVMap (gogf#4714)
1 parent f80d16c commit 7474b45

5 files changed

Lines changed: 1510 additions & 14 deletions

File tree

container/gmap/gmap_hash_k_v_map.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,54 @@ func (m *KVMap[K, V]) GetVarOrSetFuncLock(key K, f func() V) *gvar.Var {
333333
return gvar.New(m.GetOrSetFuncLock(key, f))
334334
}
335335

336+
// GetOrSetFuncWithError returns the value by key,
337+
// or sets value with returned value of callback function `f` if it does not exist
338+
// and then returns this value.
339+
//
340+
// Note that, it does not add the value to the map if the returned value of `f` is nil
341+
// or if `f` returns a non-nil error.
342+
func (m *KVMap[K, V]) GetOrSetFuncWithError(key K, f func() (V, error)) (V, error) {
343+
if v, ok := m.Search(key); ok {
344+
return v, nil
345+
}
346+
value, err := f()
347+
if err != nil {
348+
var zero V
349+
return zero, err
350+
}
351+
v, _ := m.doSetWithLockCheck(key, value)
352+
return v, nil
353+
}
354+
355+
// GetOrSetFuncLockWithError returns the value by key,
356+
// or sets value with returned value of callback function `f` if it does not exist
357+
// and then returns this value.
358+
//
359+
// GetOrSetFuncLockWithError differs with GetOrSetFuncWithError function is that it executes function `f`
360+
// with mutex.Lock of the hash map.
361+
//
362+
// Note that, it does not add the value to the map if the returned value of `f` is nil
363+
// or if `f` returns a non-nil error.
364+
func (m *KVMap[K, V]) GetOrSetFuncLockWithError(key K, f func() (V, error)) (V, error) {
365+
m.mu.Lock()
366+
defer m.mu.Unlock()
367+
if m.data == nil {
368+
m.data = make(map[K]V)
369+
}
370+
if v, ok := m.data[key]; ok {
371+
return v, nil
372+
}
373+
value, err := f()
374+
if err != nil {
375+
var zero V
376+
return zero, err
377+
}
378+
if !m.isNil(value) {
379+
m.data[key] = value
380+
}
381+
return value, nil
382+
}
383+
336384
// SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true.
337385
// It returns false if `key` exists, and `value` would be ignored.
338386
func (m *KVMap[K, V]) SetIfNotExist(key K, value V) bool {
@@ -375,6 +423,49 @@ func (m *KVMap[K, V]) SetIfNotExistFuncLock(key K, f func() V) bool {
375423
return false
376424
}
377425

426+
// SetIfNotExistFuncWithError sets value with return value of callback function `f`, and then returns true.
427+
// It returns false if `key` exists, and `value` would be ignored.
428+
// It returns (false, error) if `f` returns a non-nil error, and `value` would not be stored.
429+
func (m *KVMap[K, V]) SetIfNotExistFuncWithError(key K, f func() (V, error)) (bool, error) {
430+
if m.Contains(key) {
431+
return false, nil
432+
}
433+
value, err := f()
434+
if err != nil {
435+
return false, err
436+
}
437+
if m.isNil(value) {
438+
return true, nil
439+
}
440+
return m.SetIfNotExist(key, value), nil
441+
}
442+
443+
// SetIfNotExistFuncLockWithError sets value with return value of callback function `f`, and then returns true.
444+
// It returns false if `key` exists, and `value` would be ignored.
445+
// It returns (false, error) if `f` returns a non-nil error, and `value` would not be stored.
446+
// Note that, it does not add the value to the map if the returned value of `f` is nil.
447+
//
448+
// SetIfNotExistFuncLockWithError differs with SetIfNotExistFuncWithError function is that
449+
// it executes function `f` with mutex.Lock of the hash map.
450+
func (m *KVMap[K, V]) SetIfNotExistFuncLockWithError(key K, f func() (V, error)) (bool, error) {
451+
m.mu.Lock()
452+
defer m.mu.Unlock()
453+
if m.data == nil {
454+
m.data = make(map[K]V)
455+
}
456+
if _, ok := m.data[key]; ok {
457+
return false, nil
458+
}
459+
value, err := f()
460+
if err != nil {
461+
return false, err
462+
}
463+
if !m.isNil(value) {
464+
m.data[key] = value
465+
}
466+
return true, nil
467+
}
468+
378469
// Remove deletes value from map by given `key`, and return this deleted value.
379470
func (m *KVMap[K, V]) Remove(key K) (value V) {
380471
m.mu.Lock()

container/gmap/gmap_list_k_v_map.go

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,54 @@ func (m *ListKVMap[K, V]) GetVarOrSetFuncLock(key K, f func() V) *gvar.Var {
400400
return gvar.New(m.GetOrSetFuncLock(key, f))
401401
}
402402

403+
// GetOrSetFuncWithError returns the value by key,
404+
// or sets value with returned value of callback function `f` if it does not exist
405+
// and then returns this value.
406+
//
407+
// Note that, it does not add the value to the map if the returned value of `f` is nil
408+
// or if `f` returns a non-nil error.
409+
func (m *ListKVMap[K, V]) GetOrSetFuncWithError(key K, f func() (V, error)) (V, error) {
410+
if v, ok := m.Search(key); ok {
411+
return v, nil
412+
}
413+
value, err := f()
414+
if err != nil {
415+
var zero V
416+
return zero, err
417+
}
418+
return m.doSetWithLockCheck(key, value), nil
419+
}
420+
421+
// GetOrSetFuncLockWithError returns the value by key,
422+
// or sets value with returned value of callback function `f` if it does not exist
423+
// and then returns this value.
424+
//
425+
// GetOrSetFuncLockWithError differs with GetOrSetFuncWithError function is that it executes function `f`
426+
// with mutex.Lock of the map.
427+
//
428+
// Note that, it does not add the value to the map if the returned value of `f` is nil
429+
// or if `f` returns a non-nil error.
430+
func (m *ListKVMap[K, V]) GetOrSetFuncLockWithError(key K, f func() (V, error)) (V, error) {
431+
m.mu.Lock()
432+
defer m.mu.Unlock()
433+
if m.data == nil {
434+
m.data = make(map[K]*glist.TElement[*gListKVMapNode[K, V]])
435+
m.list = glist.NewT[*gListKVMapNode[K, V]]()
436+
}
437+
if e, ok := m.data[key]; ok {
438+
return e.Value.value, nil
439+
}
440+
value, err := f()
441+
if err != nil {
442+
var zero V
443+
return zero, err
444+
}
445+
if !m.isNil(value) {
446+
m.data[key] = m.list.PushBack(&gListKVMapNode[K, V]{key, value})
447+
}
448+
return value, nil
449+
}
450+
403451
// SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true.
404452
// It returns false if `key` exists, and `value` would be ignored.
405453
//
@@ -426,6 +474,20 @@ func (m *ListKVMap[K, V]) SetIfNotExist(key K, value V) bool {
426474
//
427475
// Note that, it does not add the value to the map if the returned value of `f` is nil.
428476
func (m *ListKVMap[K, V]) SetIfNotExistFunc(key K, f func() V) bool {
477+
if m.Contains(key) {
478+
return false
479+
}
480+
return m.SetIfNotExist(key, f())
481+
}
482+
483+
// SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true.
484+
// It returns false if `key` exists, and `value` would be ignored.
485+
//
486+
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
487+
// it executes function `f` with mutex.Lock of the map.
488+
//
489+
// Note that, it does not add the value to the map if the returned value of `f` is nil.
490+
func (m *ListKVMap[K, V]) SetIfNotExistFuncLock(key K, f func() V) bool {
429491
m.mu.Lock()
430492
defer m.mu.Unlock()
431493

@@ -443,14 +505,31 @@ func (m *ListKVMap[K, V]) SetIfNotExistFunc(key K, f func() V) bool {
443505
return true
444506
}
445507

446-
// SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true.
508+
// SetIfNotExistFuncWithError sets value with return value of callback function `f`, and then returns true.
447509
// It returns false if `key` exists, and `value` would be ignored.
510+
// It returns (false, error) if `f` returns a non-nil error, and `value` would not be stored.
448511
//
449-
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
512+
// Note that, it does not add the value to the map if the returned value of `f` is nil.
513+
func (m *ListKVMap[K, V]) SetIfNotExistFuncWithError(key K, f func() (V, error)) (bool, error) {
514+
if m.Contains(key) {
515+
return false, nil
516+
}
517+
value, err := f()
518+
if err != nil {
519+
return false, err
520+
}
521+
return m.SetIfNotExist(key, value), nil
522+
}
523+
524+
// SetIfNotExistFuncLockWithError sets value with return value of callback function `f`, and then returns true.
525+
// It returns false if `key` exists, and `value` would be ignored.
526+
// It returns (false, error) if `f` returns a non-nil error, and `value` would not be stored.
527+
//
528+
// SetIfNotExistFuncLockWithError differs with SetIfNotExistFuncWithError function is that
450529
// it executes function `f` with mutex.Lock of the map.
451530
//
452531
// Note that, it does not add the value to the map if the returned value of `f` is nil.
453-
func (m *ListKVMap[K, V]) SetIfNotExistFuncLock(key K, f func() V) bool {
532+
func (m *ListKVMap[K, V]) SetIfNotExistFuncLockWithError(key K, f func() (V, error)) (bool, error) {
454533
m.mu.Lock()
455534
defer m.mu.Unlock()
456535

@@ -459,13 +538,16 @@ func (m *ListKVMap[K, V]) SetIfNotExistFuncLock(key K, f func() V) bool {
459538
m.list = glist.NewT[*gListKVMapNode[K, V]]()
460539
}
461540
if _, ok := m.data[key]; ok {
462-
return false
541+
return false, nil
542+
}
543+
value, err := f()
544+
if err != nil {
545+
return false, err
463546
}
464-
value := f()
465547
if !m.isNil(value) {
466548
m.data[key] = m.list.PushBack(&gListKVMapNode[K, V]{key, value})
467549
}
468-
return true
550+
return true, nil
469551
}
470552

471553
// Remove deletes value from map by given `key`, and return this deleted value.

0 commit comments

Comments
 (0)