【问题标题】:How to get size of struct containing data structures in Go?如何在 Go 中获取包含数据结构的结构的大小?
【发布时间】:2018-12-28 03:21:06
【问题描述】:

我目前正在尝试获取 Go 中复杂结构的大小。

我已经阅读了使用 reflectunsafe 的解决方案,但这些解决方案都不能帮助包含数组或映射(或任何其他指向基础数据结构的指针的字段)的结构。

例子:

type testStruct struct {
    A     int
    B     string
    C     struct{}
    items map[string]string
}

如果items 包含一些值,我如何找出上面的正确字节大小?

【问题讨论】:

  • items 中值的数量不会改变testStruct 值的大小

标签: go reflection go-reflect


【解决方案1】:

通过使用反射包,您可以非常接近结构及其内容所需的内存量。您需要遍历字段并获取每个字段的大小。例如:

func getSize(v interface{}) int {
    size := int(reflect.TypeOf(v).Size())
    switch reflect.TypeOf(v).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(v)
        for i := 0; i < s.Len(); i++ {
            size += getSize(s.Index(i).Interface())
        }
    case reflect.Map:
        s := reflect.ValueOf(v)
        keys := s.MapKeys()
        size += int(float64(len(keys)) * 10.79) // approximation from https://golang.org/src/runtime/hashmap.go
        for i := range(keys) {
            size += getSize(keys[i].Interface()) + getSize(s.MapIndex(keys[i]).Interface())
        }
    case reflect.String:
        size += reflect.ValueOf(v).Len()
    case reflect.Struct:
        s := reflect.ValueOf(v)
        for i := 0; i < s.NumField(); i++ {
            if s.Field(i).CanInterface() {
                size += getSize(s.Field(i).Interface())
            }
        }
    }
    return size
}

这使用反射获得 v 的大小,然后,对于本示例中支持的类型(切片、映射、字符串和结构),它计算存储在其中的内容所需的内存。您需要在此处添加您需要支持的其他类型。

有一些细节需要解决:

  1. 不计算私有字段。
  2. 对于结构,我们会重复计算基本类型。

对于第二个,您可以在处理结构时进行递归调用之前将它们过滤掉,您可以查看reflect package 的文档中的种类。

【讨论】:

  • 你也没有得到地图结构本身的大小
  • 你是对的!我添加了一个基于golang.org/src/runtime/hashmap.go 的近似值
  • 很好的解决方案,感谢您列出您的方法的缺点。非常感谢!
猜你喜欢
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
相关资源
最近更新 更多