Go Map

基础及操作

key-value模式

1.声明

var hashMap map[keyType][valueType]
var testMap map[string]string
testMap = make(map[string]string,10)

//直接make
cites := make(map[string]string)

//直接赋值
people := map[string]string{
    "people1":"haha",
    "people2":"wawa",
}

key的类型

  • 1.可以为bool,数字,string,指针,channel,还可以是包含上述类型的借口结构体数组,但通常是int、string;
  • 2.slice、map、function不能作为key,因为这几个无法使用==判断

value的类型

  • 和key一样,通常是数字(浮点数、整数),string,struct,map
  • 声明不分配内存,需要make初始化才能赋值、使用

说明

  • key不能重复;value可以
  • map无序key value,不根据添加顺序,也不按照key排序

小练习

    students := make(map[string]map[string]string)
    students["1"] = make(map[string]string,2)
    students["1"]["name"] = "tom"
    students["1"]["sex"] = "nan"
    students["2"] = make(map[string]string,2)
    students["2"]["name"] = "mary"
    students["2"]["sex"] = "nv"

2.map 操作

增和改 map[key]=value

删除 delete(map,"key")

存在key删除,无也不报错;若想全部删除就遍历删除,或者make一个新空间,让gc处理

查找

    value,findRes = people["1"]
    if findRes{
        return value
    }else{
        return "cant find it"
    }

遍历(只有for range)

不可用for循环:map无序即无下标

    for k,v := range maps{
        fmt.Printf("k=%v,v=%v",k,v)
    }
  • 获取长度 len() len(map)
  • 按key排序
    • 1.将map的key放入切片中
    • 2.对切片排序
    • 3.遍历切片,按照key输出值
    intSort := make(map[int]int,4)
    intSort[10] = 20
    intSort[110] = 1
    intSort[40] = 5
    intSort[90] = 2

    var keys []int
    for k,_ := range intSort{
        keys = append(keys,k)
    }
    sort.Ints(keys)
    for _,k := range keys{
        fmt.Printf("map[%v]=%v",k,intSort[k])
    }

3 map切片

此处创建了map切片,还有新增map的append

    monster := make([]map[string]string,1)

    if monster[0] == nil{
        monster[0] = make(map[string]string,2)
        monster[0]["name"] = "吴亦凡"
        monster[0]["age"] = "30"
    }
    monsterNew := map[string]string{
        "name":"a",
        "age":"20",
    }
    monster = append(monster,monsterNew)

使用细节

  • 1.引用类型,故函数中会改变其值
  • 2.map可以动态增长键值对,即自动扩容
  • 3.map的value更适合管理struct

高级

1 数据结构

map 又称为 hash map,在算法上基于 hash 实现 key 的映射和寻址;在数据结构上基于桶数组实现 key-value 对的存储。

以一组 key-value 对写入 map 的流程为例进行简述:

(1)通过哈希方法取得 key 的 hash 值;

(2)hash 值对桶数组长度取模,确定其所属的桶;

(3)在桶中插入 key-value 对。

1.1 hmap

type hmap struct {
    count     int 
    flags     uint8
    B         uint8  
    noverflow uint16 
    hash0     uint32 
    buckets    unsafe.Pointer 
    oldbuckets unsafe.Pointer 
    nevacuate  uintptr       
    extra *mapextra 
}
  • count:map 中的 key-value 总数;
  • flags:map 状态标识,可以标识出 map 是否被 goroutine 并发读写;
  • B:桶数组长度的指数,桶数组长度为 2^B;
  • noverflow:map 中溢出桶的数量;
  • hash0:hash 随机因子,生成 key 的 hash 值时会使用到;
  • buckets:桶数组;
  • oldbuckets:扩容过程中老的桶数组;
  • nevacuate:扩容时的进度标识,index 小于 nevacuate 的桶都已经由老桶转移到新桶中;
  • extra:预申请的溢出桶.

1.2 mapextra

type mapextra struct {
    overflow    *[]*bmap
    oldoverflow *[]*bmap
    nextOverflow *bmap
}

在 map 初始化时,倘若容量过大,会提前申请好一批溢出桶,以供后续使用,这部分溢出桶存放在 hmap.mapextra 当中:

  • mapextra.overflow:供桶数组 buckets 使用的溢出桶;
  • mapextra.oldoverFlow: 扩容流程中,供老桶数组 oldBuckets 使用的溢出桶;
  • mapextra.nextOverflow:下一个可用的溢出桶.

1.3 bmap

const bucketCnt = 8
type bmap struct {
    tophash [bucketCnt]uint8
}
  • bmap 就是 map 中的桶,可以存储 8 组 key-value 对的数据,以及一个指向下一个溢出桶的指针;
  • 每组 key-value 对数据包含 key 高 8 位 hash 值 tophash,key 和 val 三部分;
  • 在代码层面只展示了 tophash 部分,但由于 tophash、key 和 val 的数据长度固定,因此可以通过内存地址偏移的方式寻找到后续的 key 数组、val 数组以及溢出桶指针;
  • 为方便理解,把完整的 bmap 类声明代码补充如下:
type bmap struct {
    tophash [bucketCnt]uint8
    keys [bucketCnt]T
    values [bucketCnt]T
    overflow uint8
}
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇