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")
}
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倍。
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 会有更好的性能。
http://c.biancheng.net/view/34.html https://studygolang.com/articles/23184