在go语言中,有两个内建函数分别是len(),cap(),前者用于获取容器的具体内容个数,后者用于获取容器分配的容量大小,但是这个cap对象是不能获取到map具体分配的容量大小的。有没有办法获取到呢,办法是有的,且看下文。

首先我们先使用gdb调试工具,查看一下map对象的具体结构是什么样子的。

一个及其简单的代码如下:

package main
func main() {
m := make(map[string]int)
m["a"] = 1
m["b"] = 2 }

接下来我们编译这个简单的代码,并进行调试

# go build -o test -gcflags="-N -l" main.go 这里goflags是编译时指定的参数, -N 表示禁止优化,-l表示禁止内联。 便于调试

使用gdb进行调试

# gdb test
(gdb) b main.main
Breakpoint 1 at 0x401000: file /media/sf_goproject/src/map.go, line 3.
(gdb) r # 开始运行
Starting program: /media/sf_goproject/src/test
(gdb) n
m := make(map[string]int)
(gdb) ptype m

type = struct hash<string, int> {

int count;

uint8 flags;

uint8 B;

uint32 hash0;

struct bucket<string, int> *buckets;

struct bucket<string, int> *oldbuckets;

uintptr nevacuate;

[2]*[]*runtime.bmap *overflow;

} *

从上面的调试可以看到map对象的数据结构,在golang的runtime包的的haspmap.go中有这个结构的详细介绍:

// A header for a Go map.
type hmap struct {
// Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and
// ../reflect/type.go. Don't change this structure without also changing that code!
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
hash0 uint32 // hash seed buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated) // If both key and value do not contain pointers and are inline, then we mark bucket
// type as containing no pointers. This avoids scanning such maps.
// However, bmap.overflow is a pointer. In order to keep overflow buckets
// alive, we store pointers to all overflow buckets in hmap.overflow.
// Overflow is used only if key and value do not contain pointers.
// overflow[0] contains overflow buckets for hmap.buckets.
// overflow[1] contains overflow buckets for hmap.oldbuckets.
// The first indirection allows us to reduce static size of hmap.
// The second indirection allows to store a pointer to the slice in hiter.
overflow *[2]*[]*bmap
}

所以B代表了map的容量 既然我们知道了数据的的结构,便可根据结构得到容量的内容。代码示例如下。

package main

type hmap struct {
count int
flags uint8
B uint8
hash0 uint32
buckets unsafe.Pointer
oldbuckets unsafe.Pointer
} func main() {
m := make(map[string]string)
c, b := getInfo(m)
fmt.Println("count: ", c, "b: ", b)
for i := 0; i < 10000; i++ {
m[strconv.Itoa(i)] = strconv.Itoa(i)
if i%200 == 0 {
c, b := getInfo(m)
cap := math.Pow(float64(2), float64(b))
fmt.Printf("count: %d, b: %d, load: %f\n", c, b, float64(c)/cap)
}
}
println("开始删除------")
for i := 0; i < 10000; i++ {
delete(m, strconv.Itoa(i))
if i%200 == 0 {
c, b := getInfo(m)
cap := math.Pow(float64(2), float64(b))
fmt.Println("count: ", c, "b:", b, "load: ", float64(c)/cap)
}
} debug.FreeOSMemory()
c, b = getInfo(m)
fmt.Println("释放后: ", "count: ", c, "b:", b)
} func getInfo(m map[string]string) (int, int) {
point := (**hmap)(unsafe.Pointer(&m))
value := *point
return value.count, int(value.B)
}

一些记录:
1. 在看许多文章中有说到map分配的键值被删除之后,内存是不会释放的。但是在我测试的过程中,发现内存是可以释放的。可能是版本的原因,测试的版本是1.7.1
2. map是非并发安全的,使用过程中需要自己去控制加锁。

map的容量的获取的更多相关文章

  1. 在map中根据value获取key

    原文:http://blog.csdn.net/mexican_jacky/article/details/51789548 //根据map的value获取map的key private static ...

  2. map中根据value获取key

    public static String getKeyByValue(Map map, Object value) { String keys=""; Iterator it =  ...

  3. java map遍历、排序,根据value获取key

    Map 四种遍历: Map<String,String> map = new HashMap<String, String>(); map.put("one" ...

  4. java里面获取map的key和value的方法

    获取map的key和value的方法分为两种形式: map.keySet():先获取map的key,然后根据key获取对应的value: map..entrySet():同时查询map的key和val ...

  5. Map四种获取key和value值的方法,以及对map中的元素排序(转)

    获取map的值主要有四种方法,这四种方法又分为两类,一类是调用map.keySet()方法来获取key和value的值,另一类则是通过map.entrySet()方法来取值,两者的区别在于,前者主要是 ...

  6. C++ map通过key获取value

    c++的map中通过key获取value的方法 一般是value  =map[key],或者另一种迭代器的方式 1.在map中,由key查找value时,首先要判断map中是否包含key. 2.如果不 ...

  7. cocos基础教程(5)数据结构介绍之cocos2d::Map<K,V>

    1.概述 cocos2d::Map<K,V> 是一个内部使用了 std::unordered_map的关联容器模版. std::unordered_map 是一个存储了由key-value ...

  8. ceph之crush map

    编辑crush map: 1.获取crush map: 2.反编译crush map: 3.至少编辑一个设备,桶, 规则: 4.重新编译crush map: 5.重新注入crush map: 获取cr ...

  9. Map笔记

    Map,是一个接口,是以键值对的方式存储的,并且键是无序且不可重复的.Map和Collection没有什么关系,Map是一对一对的存,而Collection是一个一个的存. 下面有一个子接口:Sort ...

随机推荐

  1. Eclipse添加servlet-api.jar库的引用

    右键Application-->Properties-->Java Build Path-->Libraries-->Add External JARs-->servle ...

  2. _ZNote_Qt_对话框_模态非模态

    QDialog(及其子类,以及所有Qt::Dialog类型的类)的对于其 parent 指针都有额外的解释:如果 parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框 ...

  3. codeforces 891 b

    B. Gluttony time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  4. AngularJS 控制器 Live Dom

    控制器的作用是在$scope对象上创建属性和方法,控制器的作用域是$scope,所以作用域是针对控制器来讲的.另外,控制器实例不是单例,每次都会重新实例化,不像服务是单例的. 其是注册在模块上的,如 ...

  5. Python自动化开发 - 装饰器

    本节内容 一.装饰器导引 1.函数对象特性 2.扩展业务功能需求 3.各种解决方案 二.装饰器解析 1.装饰器基本概念 2.无参装饰器解析 一.装饰器导引 1.函数对象特性 #### 第一波 #### ...

  6. Week Plan:强介入性的效率导师[转]

    做产品有三重境界,以效率工具这一细分领域为例: 第一重——发现用户需求,如 Fleep,敏锐地发现团队协作中的关键——聊天,围绕这一需求做足文章; 第二重——预见用户需求,如 ProcessOn,在以 ...

  7. ASP.NET写的一个博客系统

    由于域名闲置,正好也有服务器空间,短期内开发了一个博客系统. 大家都来谈  http://www.djdlt.com 目前是开放注册,免费发布.(限于空间有限,图片还是尽量少传些) 网站架构: ASP ...

  8. WPF 介绍一种在MVVM模式下弹出子窗体的方式

    主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...

  9. Unity相机跟随-----根据速度设置偏移量

    这里假设在水中的船,船有惯性,在不添加前进动力的情况下会继续移动,但是船身是可以360度自由旋转,当船的运动速度在船的前方的时候,相机会根据向前的速度的大小,设置相机的偏移量,从而提高游戏的动态带感. ...

  10. 格式化json日期'/Date(-62135596800000)/'

    日期经过json序列化之后,变成了'/Date(-62135596800000)/'字符串,在显示数据时,我们需要解释成正常的日期. Insus.NET和js库中,写了一个jQuery扩展方法: $. ...