Go-知识sync map-1. 用法

时间:2024-03-19 12:24:30

1.1 声明

sync map不需要想map那样,使用make或者使用剪短变量声明赋值初始,可以直接使用,零值为空 sync map ,不是nil.

    var sm sync.Map

1.2 增删改查

增删改查比较简单:

func TestSyncMap(t *testing.T) {
	var sm sync.Map
	// 增加或修改
	sm.Store("hi", "hello")
	// 查询
	// 查询返回 value, bool,必须显示忽略 bool
	v, ok := sm.Load("hi")
	fmt.Printf("time : %s, v = %s, ok = %v", time.Now().Format(T_F), v, ok)
	// 删除
	sm.Delete("hi")
	wd := sync.WaitGroup{}
	wd.Add(2)
	fmt.Printf("time : %s , start\n", time.Now().Format(T_F))
	go func() {
		rand.Seed(time.Now().UnixNano())
		fmt.Printf("time : %s , sleep\n", time.Now().Format(T_F))
		time.Sleep(time.Duration(rand.Intn(10)) * time.Second)
		// 查询并增加,返回 oldV, bool , 如果 key 已经有值,返回 v 和 true ,否则返回 nil 和 false
		oldValue, isExists := sm.LoadOrStore("hi", "world")
		fmt.Printf("time : %s ,old := %s , is Exists : %v\n", time.Now().Format(T_F), oldValue, isExists)
		wd.Done()
	}()
	go func() {
		rand.Seed(time.Now().UnixNano())
		fmt.Printf("time : %s , sleep\n", time.Now().Format(T_F))
		time.Sleep(time.Duration(rand.Intn(5)) * time.Second)
		oldValue, isExists := sm.LoadOrStore("hi", "worldX")
		fmt.Printf("time : %s ,old := %s , is Exists : %v\n", time.Now().Format(T_F), oldValue, isExists)
		fmt.Printf("time : %s ,delete map\n", time.Now().Format(T_F))
		sm.Delete("hi")
		wd.Done()
	}()
	wd.Wait()
}

在这里插入图片描述

与map不同的是,sync map 不能使用[]来指定key,因为map是标准库提供的,编译的时候会做链接。
还需要注意一点,sync map 能存储任何类型的key-value,key不在限制为基本类型。
但是这也意味着,如果无法保证value的类型,那么在使用的时候,需要使用类型断言。

1.3 增强操作

除了map中的简单的增删改查之外,还有一些结合了查询的操作。

  • LoadOrStore
// LoadOrStore returns the existing value for the key if present.
// LoadOrStore 返回旧值,如果不存在,返回给定的值
// Otherwise, it stores and returns the given value.
// The loaded result is true if the value was loaded, false if stored.
// 如果有旧值,返回true,否则返回false
func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) {}
  • LoadAndDelete
// LoadAndDelete deletes the value for a key, returning the previous value if any.
// LoadAndDelete 删除给定的key,如果存在,返回值,如果不存在返回 nil
// The loaded result reports whether the key was present.
// 如果给定的key对应的只存在,返回true,否则返回false
func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) {}
  • Range
func (m *Map) Range(f func(key, value interface{}) bool) {} 

sync map无法像map一样使用range进行遍历,所以提供了Range方法实现遍历能力。 Range会遍历每一个key-value,并对每一个key-value调用传入的函数,实现遍历。

因为sync map支持并发读写,遍历期间可能读取到其他goroutine写入的数据。也就是说,遍历过程中,map是动态变化的。