Concurrent Safety

gmap supports a concurrency-safe option switch, which is not concurrency-safe by default. Developers can choose to enable the concurrency-safe feature of gmap (passing the initialization switch parameter safe value as true, it must be set during initialization and cannot be dynamically set at runtime). For example:

  1. m := gmap.New(true)

Not only the gmap module, but other concurrent-safe data structures of the goframe framework also support the concurrent safety feature switch.

Usage Example

Basic Usage

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. )
  6. func main() {
  7. // Create a default gmap object,
  8. // By default, this gmap object does not support concurrency safety features,
  9. // A true parameter can be given during initialization to enable concurrent safety features.
  10. m := gmap.New()
  11. // Set key-value pairs
  12. for i := 0; i < 10; i++ {
  13. m.Set(i, i)
  14. }
  15. // Query size
  16. fmt.Println(m.Size())
  17. // Batch set key-value pairs (different data type objects have different parameters)
  18. m.Sets(map[interface{}]interface{}{
  19. 10: 10,
  20. 11: 11,
  21. })
  22. fmt.Println(m.Size())
  23. // Check if it exists
  24. fmt.Println(m.Contains(1))
  25. // Query value
  26. fmt.Println(m.Get(1))
  27. // Delete item
  28. m.Remove(9)
  29. fmt.Println(m.Size())
  30. // Batch delete
  31. m.Removes([]interface{}{10, 11})
  32. fmt.Println(m.Size())
  33. // Current key list (random order)
  34. fmt.Println(m.Keys())
  35. // Current value list (random order)
  36. fmt.Println(m.Values())
  37. // Query key name, and write the given default value when the key value does not exist
  38. fmt.Println(m.GetOrSet(100, 100))
  39. // Delete key-value pair, returning the corresponding key value
  40. fmt.Println(m.Remove(100))
  41. // Traverse map
  42. m.Iterator(func(k interface{}, v interface{}) bool {
  43. fmt.Printf("%v:%v ", k, v)
  44. return true
  45. })
  46. // Custom write lock operation
  47. m.LockFunc(func(m map[interface{}]interface{}) {
  48. m[99] = 99
  49. })
  50. // Custom read lock operation
  51. m.RLockFunc(func(m map[interface{}]interface{}) {
  52. fmt.Println(m[99])
  53. })
  54. // Clear map
  55. m.Clear()
  56. // Check if the map is empty
  57. fmt.Println(m.IsEmpty())
  58. }

After execution, the output is:

  1. 12
  2. true
  3. 1
  4. 11
  5. 9
  6. [0 1 2 4 6 7 3 5 8]
  7. [3 5 8 0 1 2 4 6 7]
  8. 100
  9. 100
  10. 3:3 5:5 8:8 7:7 0:0 1:1 2:2 4:4 6:6 99
  11. true

Ordered Traversal

Let’s take a look at examples of ordered traversal for three different types of map.

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/frame/g"
  5. "github.com/gogf/gf/v2/container/gmap"
  6. "github.com/gogf/gf/v2/util/gutil"
  7. )
  8. func main() {
  9. array := g.Slice{2, 3, 1, 5, 4, 6, 8, 7, 9}
  10. hashMap := gmap.New(true)
  11. listMap := gmap.NewListMap(true)
  12. treeMap := gmap.NewTreeMap(gutil.ComparatorInt, true)
  13. for _, v := range array {
  14. hashMap.Set(v, v)
  15. }
  16. for _, v := range array {
  17. listMap.Set(v, v)
  18. }
  19. for _, v := range array {
  20. treeMap.Set(v, v)
  21. }
  22. fmt.Println("HashMap Keys:", hashMap.Keys())
  23. fmt.Println("HashMap Values:", hashMap.Values())
  24. fmt.Println("ListMap Keys:", listMap.Keys())
  25. fmt.Println("ListMap Values:", listMap.Values())
  26. fmt.Println("TreeMap Keys:", treeMap.Keys())
  27. fmt.Println("TreeMap Values:", treeMap.Values())
  28. }

After execution, the output is:

  1. HashMap Keys: [4 6 8 7 9 2 3 1 5]
  2. HashMap Values: [6 8 4 3 1 5 7 9 2]
  3. ListMap Keys: [2 3 1 5 4 6 8 7 9]
  4. ListMap Values: [2 3 1 5 4 6 8 7 9]
  5. TreeMap Keys: [1 2 3 4 5 6 7 8 9]
  6. TreeMap Values: [1 2 3 4 5 6 7 8 9]

FilterEmpty/FilterNil Empty Value Filtering

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. "github.com/gogf/gf/v2/frame/g"
  6. )
  7. func main() {
  8. m1 := gmap.NewFrom(g.MapAnyAny{
  9. "k1": "",
  10. "k2": nil,
  11. "k3": 0,
  12. "k4": 1,
  13. })
  14. m2 := gmap.NewFrom(g.MapAnyAny{
  15. "k1": "",
  16. "k2": nil,
  17. "k3": 0,
  18. "k4": 1,
  19. })
  20. m1.FilterEmpty()
  21. m2.FilterNil()
  22. fmt.Println(m1.Map())
  23. fmt.Println(m2.Map())
  24. // Output:
  25. // map[k4:1]
  26. // map[k1: k3:0 k4:1]
  27. }

Flip Key-Value Pair Reversal

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. "github.com/gogf/gf/v2/frame/g"
  6. )
  7. func main() {
  8. var m gmap.Map
  9. m.Sets(g.MapAnyAny{
  10. "k1": "v1",
  11. "k2": "v2",
  12. })
  13. m.Flip()
  14. fmt.Println(m.Map())
  15. // May Output:
  16. // map[v1:k1 v2:k2]
  17. }

Keys/Values Key/Value Lists

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. "github.com/gogf/gf/v2/frame/g"
  6. )
  7. func main() {
  8. var m gmap.Map
  9. m.Sets(g.MapAnyAny{
  10. "k1": "v1",
  11. "k2": "v2",
  12. "k3": "v3",
  13. "k4": "v4",
  14. })
  15. fmt.Println(m.Keys())
  16. fmt.Println(m.Values())
  17. // May Output:
  18. // [k1 k2 k3 k4]
  19. // [v2 v3 v4 v1]
  20. }

Pop/Pops Random Pop

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. "github.com/gogf/gf/v2/frame/g"
  6. )
  7. func main() {
  8. var m gmap.Map
  9. m.Sets(g.MapAnyAny{
  10. "k1": "v1",
  11. "k2": "v2",
  12. "k3": "v3",
  13. "k4": "v4",
  14. })
  15. fmt.Println(m.Pop())
  16. fmt.Println(m.Pops(2))
  17. fmt.Println(m.Size())
  18. // May Output:
  19. // k1 v1
  20. // map[k2:v2 k4:v4]
  21. // 1
  22. }

SetIfNotExist* Conditional Setting

Conditional setting means writing to the map only when the specified key does not exist, and the method returns true; otherwise, it ignores the write and the method returns false. Relevant methods include:

  • SetIfNotExist
  • SetIfNotExistFunc
  • SetIfNotExistFuncLock

For detailed descriptions, please refer to the interface documentation or source code comments.

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. )
  6. func main() {
  7. var m gmap.Map
  8. fmt.Println(m.SetIfNotExist("k1", "v1"))
  9. fmt.Println(m.SetIfNotExist("k1", "v1"))
  10. fmt.Println(m.Map())
  11. // Output:
  12. // true
  13. // false
  14. // map[k1:v1]
  15. }

Merge Dictionary Merge

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/container/gmap"
  5. )
  6. func main() {
  7. var m1, m2 gmap.Map
  8. m1.Set("key1", "val1")
  9. m2.Set("key2", "val2")
  10. m1.Merge(&m2)
  11. fmt.Println(m1.Map())
  12. // May Output:
  13. // map[key1:val1 key2:val2]
  14. }

JSON Serialization/Deserialization

All container types under the gmap module implement the standard library json data format serialization/deserialization interfaces.

1. Marshal

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gogf/gf/v2/frame/g"
  6. "github.com/gogf/gf/v2/container/gmap"
  7. )
  8. func main() {
  9. m := gmap.New()
  10. m.Sets(g.MapAnyAny{
  11. "name": "john",
  12. "score": 100,
  13. })
  14. b, _ := json.Marshal(m)
  15. fmt.Println(string(b))
  16. }

After execution, the output is:

  1. {"name":"john","score":100}
  1. Unmarshal
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gogf/gf/v2/container/gmap"
  6. )
  7. func main() {
  8. m := gmap.Map{}
  9. s := []byte(`{"name":"john","score":100}`)
  10. json.Unmarshal(s, &m)
  11. fmt.Println(m.Map())
  12. }

After execution, the output is:

  1. map[name:john score:100]