Golang学习笔记之集合(map)

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

• 引⽤类型,哈希表。
• 键必须是⽀持相等运算符 (==、 !=) 类型,⽐如 number、 string、pointer、 array、 struct,以及对应的 interface。
• 值可以是任意类型,没有限制。

•map 的 0 值为 nil。试图给一个 nil map 添加元素给会导致运行时错误。

一、申明和初始化

可以通过将键和值的类型传递给内置函数 make 来创建一个 map。一般语法为:
make(map[KeyType]ValueType)。
例如:
personSalary := make(map[string]int)
上面的代码创建了一个名为 personSalary 的 map。其中键的类型为 string,值的类型为 int。

初始化
    mymap := make(map[string]string)
    mymap["name"] = "张三"
    mymap["professional"] = "全栈"
    fmt.Println(mymap)

方式二

var m map[string]int = map[string]int{"id":12,"age":20}

二、map的新增和修改

map通过键值的方式进行新增,修改也是通过键

    mymap := make(map[string]string)
    mymap["name"] = "张三"
    mymap["professional"] = "全栈" //给map添加professional健
    fmt.Println(mymap)           //map[name:张三 professional:全栈]
    mymap["professional"] = "后台" //修改professional键对应的值
    fmt.Println(mymap)           //map[name:张三 professional:后台]

三、访问map元素,map通过键获取值

    fmt.Println(mymap["name"])   //张三

四、map可以通过len来获取长度,cap无效

    fmt.Println(len(mymap))      //2

五、删除元素,delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。

    delete(mymap, "name")
    fmt.Println(mymap) //map[professional:后台]

六、判断key是否存在

value, ok := map[key]
上面的语法可以检测一个特定的键是否存在于 map 中。如果 ok 是true,则键存在,value 被赋值为对应的值。如果 ok 为 false,则表示键不存在。

    value, ok := mymap["name"]
    fmt.Println(value, ok) //张三 true

七、遍历。range for 可用于遍历 map 中所有的元素

    for k, v := range mymap { // 迭代,可仅返回 key。随机顺序返回,每次都不相同。
        println(k, v)
    }

从 map 中取回的是⼀个 value 临时复制品,对其成员的修改是没有任何意义的。
可以在迭代时安全删除键值。

for k, v := range mymap { // 迭代,可仅返回 key。随机顺序返回,每次都不相同。
        println(k, v)
        delete(mymap,k)
    }

八、比较 map,map 不能通过 == 操作符比较是否相等。== 操作符只能用来检测map 是否为 nil。

下面写了一个比较map的函数

//判断两个map是否相等
func comparisonMap(map1 ,map2 map[string]string) bool {
    //判断长度
    if len(map1) != len(map2) {
        return false
    }
    //判断值
    for key, value := range map1 {
        if value !=map2[key] {
            return false
        }
    }
    return true
}

九、线程安全

在很多时候,我们会并发地使用map对象,尤其是在一定规模的项目中,map总会保存goroutine共享的数据。在Go官方blog的Go maps in action一文中,提供了一种简便的解决方案。
地址https://blog.golang.org/go-maps-in-action需要翻墙

var counter = struct{
    sync.RWMutex
    m map[string]int
}{m: make(map[string]int)}

嵌入一个结构体为map增加一个读写锁。
读数据的时候很方便的加锁:

counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)

写数据的时候,写锁

counter.Lock()
counter.m["some_key"]++
counter.Unlock()

示例

type MyMap struct {
    v map[string]string
    sync.RWMutex
}

func (this *MyMap) Put(key string, value string) {
    this.Lock()
    defer this.Unlock()
    this.v[key] = value
}
func (this *MyMap) Get(key string) string {
    this.RLock()
    defer this.RUnlock()
    return this.v[key]
}

你可能感兴趣的:(Golang学习笔记之集合(map))