44

Golang学习笔记之集合(map)

 5 years ago
source link: https://studygolang.com/articles/16784?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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{"name":张三,"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]
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK