如何在Go中获取包含数据结构的struct的大小?

1u4esq0p  于 5个月前  发布在  Go
关注(0)|答案(2)|浏览(96)

我目前正在尝试获取Go中复杂结构的大小。
我读过使用reflectunsafe的解决方案,但这两种解决方案都不能帮助包含数组或Map(或任何其他指向底层数据结构的字段)的结构。
范例:

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

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

i5desfxk

i5desfxk1#

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

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
}

字符串
它使用reflect获取v的大小,然后,对于这个例子中支持的类型(切片,Map,字符串和结构),它计算存储在其中的内容所需的内存。你需要在这里添加你需要支持的其他类型。
有几个细节需要解决:
1.私有字段不计算在内。
1.对于结构,我们重复计算基本类型。
对于第二点,你可以在处理结构体的时候,在递归调用之前过滤掉它们,你可以在reflect包的文档中查看这些类型。

olmpazwi

olmpazwi2#

扩展另一个答案,如果你想得到指针对象的大小,那么我们需要首先解引用它,如下所示,因为它是解引用的,所以我们还必须将类型改为struct,

func getSize(v interface{}) int {
size := int(reflect.TypeOf(v).Size())
kind := reflect.TypeOf(v).Kind()

//dereferencing begins 
if kind == reflect.Pointer {
    s := reflect.ValueOf(v)
    if !s.IsNil() {
        v = reflect.ValueOf(v).Elem().Interface()
        kind = reflect.TypeOf(v).Kind()
    }
}
switch 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())
        }
    }
case reflect.Interface:
    s := reflect.ValueOf(v)
    for i := 0; i < s.NumField(); i++ {
        size += getSize(s.Field(i).Interface())
    }
}

return size

字符串
}

相关问题