如何在golang中获取结构体及其内容的字节数大小?

11

我有一个结构体,比如:

type ASDF struct {
    A   uint64
    B   uint64
    C   uint64
    D   uint64
    E   uint64
    F   string
}

我创建了一个该结构体的切片:a := []ASDF{}

我对该结构体的切片执行操作(添加/删除/更新不同内容的结构体),那么如何获取该切片及其内容的字节总大小(用于内存)?是否有内置函数可以做到这一点,还是需要手动使用unsafe.Sizeof进行计算,然后len每个字符串?


一个快速的问题,结构体 ASDF 不是由于声明所有变量类型而是固定大小的吗?那么你只需将 ASDF 的结构体指针大小乘以 len(a),因为您只能将相同大小的元素附加到切片中。或者我误解了切片的工作方式? - Anzel
1
string 字段可能会出现问题。 - Kaveh Shahbazian
2个回答

8

计算所有内存的大小,不包括垃圾收集器和其他开销。例如:

package main

import (
    "fmt"
    "unsafe"
)

type ASDF struct {
    A uint64
    B uint64
    C uint64
    D uint64
    E uint64
    F string
}

func (s *ASDF) size() int {
    size := int(unsafe.Sizeof(*s))
    size += len(s.F)
    return size
}

func sizeASDF(s []ASDF) int {
    size := 0
    s = s[:cap(s)]
    size += cap(s) * int(unsafe.Sizeof(s))
    for i := range s {
        size += (&s[i]).size()
    }
    return size
}

func main() {
    a := []ASDF{}

    b := ASDF{}
    b.A = 1
    b.B = 2
    b.C = 3
    b.D = 4
    b.E = 5
    b.F = "ASrtertetetetetetetDF"
    fmt.Println((&b).size())
    a = append(a, b)

    c := ASDF{}
    c.A = 10
    c.B = 20
    c.C = 30
    c.D = 40
    c.E = 50
    c.F = "ASetDF"
    fmt.Println((&c).size())
    a = append(a, c)

    fmt.Println(len(a))
    fmt.Println(cap(a))
    fmt.Println(sizeASDF(a))
}

输出:

69
54
2
2
147

http://play.golang.org/p/5z30vkyuNM


我不明白 cap(s) * 是干嘛的?这不会导致错误的结果吗? - renskiy

3
很抱歉,如果您想得到任何结果,unsafe.Sizeof 是您要走的路。结构的内存大小不是您应该依赖的东西。请注意,即使 unsafe.Sizeof 的结果也是不准确的:运行时可能会添加头部数据以帮助垃圾回收,而您无法观察到这些数据。
对于您的特定示例(查找缓存大小),我建议您使用一个对许多处理器都合理的静态大小。在几乎所有情况下,进行这样的微小优化是不值得的。

len(...) 函数似乎只能用于数组、字符串、切片和通道。对于结构体没有帮助 =( - maerics
@maerics 为了更好地理解你想要实现什么,你认为这些信息有什么用处? - fuz
1
@FUZxxl:我不知道,问问楼主吧 =) 我只是在旁观者中发表评论。 - maerics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接