go语言中map函数 golang map key struct

golang变量(二)——map和slice详解衍生类型,interface{} , map, [],struct等
map类似于java的hashmap,python的dict,php的hash array 。
常规的for循环 , 可以用for k,v :=range m {}. 但在下面清空有一个坑注意go语言中map函数:
著名的map[string]*struct 副本问题
结果:
Go 中不存在引用传递 , 所有的参数传递都是值传递,而map是等同于指针类型的,所以在把map变量传递给函数时 , 函数对map的修改,也会实质改变map的值 。
slice类似于其go语言中map函数他语言的数组(list,array),slice初始化和map一样,这里不在重复
除了Pointer数组外,len表示使用长度,cap是总容量,make([]int, len, cap)可以预申请 比较大的容量,这样可以减少容量拓展的消耗 , 前提是要用到 。
cap是计算切片容量 , len是计算变量长度的,两者不一样 。具体例子如下:
结果:
分析:cap是计算当前slice已分配的容量大?。?采用的是预分配的伙伴算法(当容量满时,拓展分配一倍的容量) 。
append是slice非常常用的函数,用于添加数据到slice中,但如果使用不好,会有下面的问题:
预期是[1 2 3 4 5 6 7 8 9 10],[1 2 3 4 5 6 7 8 9 10 11 12],但实际结果是:
注意slice是值传递,修改一下:
输出如下:
== 只能用于判断常规数据类型,无法使用用于slice和map判断,用于判断map和slice可以使用reflect.DeepEqual,这个函数用了递归来判断每层的k,v是否一致 。
当然还有其他方式,比如转换成json,但小心有一些异常的bug , 比如html编码,具体这个json问题 , 待后面在分析 。
goland map底层原理map 是Go语言中基础的数据结构,在日常的使用中经常被用到 。但是它底层是如何实现的呢?
总体来说golang的map是hashmap , 是使用数组+链表的形式实现的,使用拉链法消除hash冲突 。
golang的map由两种重要的结构,hmap和bmap(下文中都有解释),主要就是hmap中包含一个指向bmap数组的指针,key经过hash函数之后得到一个数 , 这个数低位用于选择bmap(当作bmap数组指针的下表),高位用于放在bmap的[8]uint8数组中,用于快速试错 。然后一个bmap可以指向下一个bmap(拉链) 。
Golang中map的底层实现是一个散列表,因此实现map的过程实际上就是实现散表的过程 。在这个散列表中 , 主要出现的结构体有两个,一个叫 hmap (a header for a go map),一个叫 bmap (a bucket for a Go map,通常叫其bucket) 。这两种结构的样子分别如下所示:
hmap :
图中有很多字段,但是便于理解map的架构,你只需要关心的只有一个 , 就是标红的字段: buckets数组。Golang的map中用于存储的结构是bucket数组 。而bucket(即bmap)的结构是怎样的呢?
bucket :
相比于hmap,bucket的结构显得简单一些,标红的字段依然是“核心”,我们使用的map中的key和value就存储在这里 。“高位哈希值”数组记录的是当前bucket中key相关的“索引”,稍后会详细叙述 。还有一个字段是一个指向扩容后的bucket的指针,使得bucket会形成一个链表结构 。例如下图:
由此看出hmap和bucket的关系是这样的:
而bucket又是一个链表 , 所以,整体的结构应该是这样的:
哈希表的特点是会有一个哈希函数,对你传来的key进行哈希运算,得到唯一的值,一般情况下都是一个数值 。Golang的map中也有这么一个哈希函数,也会算出唯一的值 , 对于这个值的使用,Golang也是很有意思 。
Golang把求得的值按照用途一分为二:高位和低位 。

推荐阅读