【问题标题】:GoLang - memory allocation - []byte vs stringGoLang - 内存分配 - []字节与字符串
【发布时间】:2019-09-18 03:44:05
【问题描述】:

在下面的代码中:

c := "fool"
d := []byte("fool")
fmt.Printf("c: %T, %d\n", c, unsafe.Sizeof(c)) // 16 bytes
fmt.Printf("d: %T, %d\n", d, unsafe.Sizeof(d)) // 24 bytes

要确定从 CloudFoundry 接收 JSON 数据所需的数据类型,我正在测试上面的示例代码以了解 []bytestring 类型的内存分配。


string 类型变量 c 的预期大小为 1 字节 x 4 ascii 编码字母 = 4 字节,但大小显示为 16 字节。

对于byte 类型变量d,GO 将字符串作为字符串文字嵌入到可执行程序中。它在运行时使用runtime.stringtoslicebyte 函数将字符串文字转换为字节切片。有点像...[]byte{102, 111, 111, 108}

byte 类型变量 d 的预期大小再次为 1 字节 x 4 ascii 值 = 4 字节,但变量 d 的大小显示为 24 字节,因为它是底层数组容量。


为什么两个变量的大小都不是4字节?

【问题讨论】:

    标签: string go memory size


    【解决方案1】:

    Go 中的切片和字符串都是类似结构的头文件:

    reflect.SliceHeader:

    type SliceHeader struct {
            Data uintptr
            Len  int
            Cap  int
    }
    

    reflect.StringHeader:

    type StringHeader struct {
            Data uintptr
            Len  int
    }
    

    unsafe.Sizeof() 报告的大小是这些标头的大小,不包括指向数组的大小:

    Sizeof 接受任何类型的表达式 x 并返回假设变量 v 的大小(以字节为单位),就好像 v 是通过 var v = x 声明的一样。 大小不包括 x 可能引用的任何内存。例如,如果 x 是切片,则 Sizeof 返回切片描述符的大小,而不是切片引用的内存大小。 p>

    要获得某个任意值的实际(“递归”)大小,请使用 Go 的内置测试和基准测试框架。详情见How to get memory size of variable in Go?

    对于字符串,请参阅String memory usage in Golangstring 值所需的完整内存可以这样计算:

    var str string = "some string"
    
    stringSize := len(str) + int(unsafe.Sizeof(str))
    

    【讨论】:

    • 那么,我可以认为这个答案无效吗? stackoverflow.com/a/26975872/3317808
    • @overexchange 同样,正如我在回答中强调的那样,unsafe.Sizeof() 返回的值不包括该值可能引用的任何内存。这意味着保存切片或字符串的实际字节所需的内存没有被它覆盖。
    • 我明白...我的问题是.. 将此answer 评论为无效不重要吗?
    • @overexchange 这取决于您如何定义“大小”。如果您也需要引用/指出的大小,那么它是无效的。
    • @overexchange 是的,因为切片值或字符串值只是标题。这是保存切片或字符串标头所需的内存。但是,如果您想知道分配/创建它们需要多少内存,则需要包括这些标头指向的数组的大小。
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2011-03-22
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多