假如有一个map: {“name”:“白小白”,“age”:“18”}
package main
import (
"fmt"
)
func main() {
// 第一种定义方法,并初始化十个位置
// m := make(map[string]string, 10)
// 第二种定义map
m := map[string]string{"name": "baixiaobai", "sex": "男"}
// 修改变量
m["sex"] = "女"
// 新增变量
m["age"] = "20"
// 删除变量
delete(m, "sex")
// 查看
for key, val := range m{
fmt.Println(key)
fmt.Println(val)
}
fmt.Printf("m is %s\n", m)
// 第三种,这种适用于整体赋值,引用
// var row map[string]string
row := m
row["name"] = "白小黑"
fmt.Printf("m is %s\n", m)
fmt.Printf("row is %s\n", row)
// 第四种,这种适用于整体赋值,引用
// m := new(map[string]string)
}
go种的map有自己的一套实现原理,其核心是hmap和bmap两个结构体实现
hmap结构体不存放具体的kv,具体的kv是放在bmap中,我们通常称之为桶
hint. B
0-8 0
9-13 1
14-26 2
由此可知,这次创建的桶数组为2个,可以存放16个kv,注意,这个B也不是一成不变的,有一定的规则
注意:每个bmap中可以存储8个键值对,当不够存储是需要使用溢出桶,并将当前bamp中的overflow字段指向溢出桶的位置
在向map中添加数据时,当达到一定条件后,则会发生扩容
扩容条件:
import "sync"
type SafeDict struct {
data map[string]int
*sync.RWMutex
}
func NewSafeDict(data map[string]int) *SafeDict {
return &SafeDict{data, &sync.RWMutex{}}
}
func (d *SafeDict) Len() int {
d.RLock()
defer d.RUnlock()
return len(d.data)
}
func (d *SafeDict) Put(key string, value int) (int, bool) {
d.Lock()
defer d.Unlock()
old_value, ok := d.data[key]
d.data[key] = value
return old_value, ok
}
func (d *SafeDict) Get(key string) (int, bool) {
d.RLock()
defer d.RUnlock()
old_value, ok := d.data[key]
return old_value, ok
}
func (d *SafeDict) Delete(key string) (int, bool) {
d.Lock()
defer d.Unlock()
old_value, ok := d.data[key]
if ok {
delete(d.data, key)
}
return old_value, ok
}