golang Map使用及源码分析

golang Map使用及源码分析

许多散列表实现存在不同的属性,但通常它们提供快速查找,添加和删除。Go提供了一个内置的map 类型,去实现一个哈希表。

声明与初始化

声明 一个 map 类型像这样:

map[keyType]valueType
键(key)的类型可以是任意可比较的类型,值(value)的类型可以是任意类型,甚至是另一个 map 类型。
下面的变量 m 是一个字符串键到int值的映射:

m = make(map[string]int)

make函数将分配并初始化一个散列 map 数据结构,并返回指向它的指针。该数据结构的细节是运行时的实现细节,并不是由语言本身指定的。 在本文中,我们将重点介绍地图的使用,而不是它们的实现。

使用 map

Go 提供了一种大家熟悉的语法去使用 map. 下面语句将设置 字符串 为"route"的key 映射 到值为66 的value:

使用 map

Go 提供了一种大家熟悉的语法去使用 map. 下面语句将设置 字符串 为"route"的key 映射 到值为66 的value:
Go 提供了一种大家熟悉的语法去使用 map. 下面语句将设置 字符串 为"route"的key 映射 到值为66 的value:

m[“route”] = 66

该语句检索key 为 “route” 的值, 并将它赋值给新的变量 i :

i := m[“route”]

如果请求的 key 不存在,我们将返回value Type 的空值。例子中情况下,值类型为 int, 因此值为 0:

j := m[“root”]

// j == 0

使用内置的 len 函数返回map 的长度(多少个已赋值的 key )
n := len(m)

使用内置的delete 函数来删除 map 的一条映射:

delete(m, “route”)

fmt.Println(len(m))

// 0

当你删除一个不存在的 key 时,它不会做执行任何操作( 不会报错)

一个有两个的返回值用来测试 是否 存在该key:

i, ok := m[“route”]

在这个语句中,第一个值 i 被分配到 key 为“route”映射的值。如果该 key 不存在,返回值类型的空值. 第二个值 ok 是一个 bool 类型,如果该 key 存在于map中,则为 true, 如果没有,则为false。

如果你要在不检索值的情况下,测试一个 key , 可以用 下划线 代替第一个变量:

_, ok := m[“route”]

遍历一个map:
for key, value := range m {

        fmt.Println("key:", key, "value:", value)

}

利用空值

例如,布尔值的映射可以用作一组集合类的数据结构(请记住,布尔类型的空值是false)。此示例遍历节点的链接列表并打印其值。它使用一个 map 节点指针来检测列表中的循环。

    type Node struct {

            Next    *Node

            Value    interface{}

    }

    var first *Node

    visited := make(map[*Node]bool)

    for n := first; n != nil;  n = n.Next {

            if vistied[n] {

                    fmt.Println("cycle detected")

                    break

            }

            visited[n] = true

            fmt.Println(n.Value)

    }

如果 n 已被访问, 则表达式 visited[n] 为真, 如果 n 不存在则为 false. 没有必要使用双值形式来测试 map 中是否存在n; 空值默认已为我们做了。

数据结构

哈希表的数据结构中一些关键的域如下所示:

struct Hmap
{
uint8 B; // 可以容纳2^B个项
uint16 bucketsize; // 每个桶的大小

byte    *buckets;     // 2^B个Buckets的数组
byte    *oldbuckets;  // 前一个buckets,只有当正在扩容时才不为空

};
上面给出的结构体只是Hmap的部分的域。需要注意到的是,这里直接使用的是Bucket的数组,而不是Bucket*指针的数组。这意味着,第一个Bucket和后面溢出链的Bucket分配有些不同。第一个Bucket是用的一段连续的内存空间,而后面溢出链的Bucket的空间是使用mallocgc分配的。

这个hash结构使用的是一个可扩展哈希的算法,由hash值mod当前hash表大小决定某一个值属于哪个桶,而hash表大小是2的指数,即上面结构体中的2^B。每次扩容,会增大到上次大小的两倍。结构体中有一个buckets和一个oldbuckets是用来实现增量扩容的。正常情况下直接使用buckets,而oldbuckets为空。如果当前哈希表正在扩容中,则oldbuckets不为空,并且buckets大小是oldbuckets大小的两倍。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值