Skip to content

Files

Latest commit

1c74697 · May 26, 2022

History

History
169 lines (125 loc) · 3.82 KB

2.4.md

File metadata and controls

169 lines (125 loc) · 3.82 KB

2.4 map

Map 是一种无序的键值对的集合,一个key=>value的hash结构

声明:

var map1 map[keytype]valuetype

示例:

 var  mapLit map[string]int   
  未初始化的 map 的值是 nil

初始化

m = map[string]int{}

m=make(map[string]int)

声明和初始化简写如下

m := map[string]int{"one": 1, "two": 2}

赋值

var m map[string]int
m = map[string]int{"one": 1, "two": 2}
m["d"] = 2
fmt.Println(m)

多维map

	m := map[string]map[string]int{}
	d := map[string]int{}
	d["b"] = 23
	m["a"] = d
	fmt.Println(m)

删除单个元素

	var m map[string]int
	m = map[string]int{"one": 1, "two": 2}	
	fmt.Println(m)
	delete(m, "one") //删除key为 one
	fmt.Println(m, len(m))

删除整个map元素

	var m map[string]int
	m = map[string]int{"one": 1, "two": 2}
	m = nil//清空map 元素
	fmt.Println(m, len(m))

判断key存不存在

var m map[string]int
m = map[string]int{"one": 1, "two": 2}
if _,ok:=m["one"];!ok{
	fmt.Println("The key does not exist")
}

比较两个map

package main

import (
   "fmt"
   "reflect"
)

func main() {
   m1 := map[string]int{"a": 1, "b": 2, "c": 3}
   m2 := map[string]int{"a": 1, "c": 3, "b": 2}
   //方法一
   fmt.Println(reflect.DeepEqual(m1, m2))
   //方法二
   fmt.Println(cmpMap(m1, m2))
}
func cmpMap(m1, m2 map[string]int) bool {
   if len(m1) == len(m2) {
      for k1, v1 := range m1 {
         if v2, ok := m2[k1]; ok {
            if v1 != v2 {
               return false
            }
         } else {
            return false
         }
      }
      return true
   }
   return false
}

其中方法一用到了反射,效率相对比较低,相差大约10倍。

sync.Map

Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。 在 2017 年发布的 Go 1.9 中正式加入了并发安全的字典类型sync.Map。这个字典类型提供了一些常用的键值存取操作方法,并保证了这些操作的并发安全。同时,它的存、取、删等操作都可以基本保证在常数时间内执行完毕。换句话说,它们的算法复杂度与map类型一样都是O(1)的。在有些时候,与单纯使用原生map和互斥锁的方案相比,使用sync.Map可以显著地减少锁的争用。sync.Map本身虽然也用到了锁,但是,它其实在尽可能地避免使用锁。 sync.Map 有以下特性: 无须初始化,直接声明即可。 sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。

使用很简单,示例如下:

package main

import (
      "fmt"
      "sync"
)

func main() {

    var scene sync.Map

    // 将键值对保存到sync.Map
    scene.Store("greece", 97)
    scene.Store("london", 100)
    scene.Store("egypt", 200)

    // 从sync.Map中根据键取值
    fmt.Println(scene.Load("london"))

    // 根据键删除对应的键值对
    scene.Delete("london")

    // 遍历所有sync.Map中的键值对
    scene.Range(func(k, v interface{}) bool {

        fmt.Println("iterate:", k, v)
        return true
    })

}

sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。

links

http://c.biancheng.net/view/34.html https://studygolang.com/articles/23184