GoLang-内存分配-[]字节与字符串

ove*_*nge 2 memory string size go

在下面的代码中:

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
Run Code Online (Sandbox Code Playgroud)

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


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个字节?

icz*_*cza 8

Go中的slice和string都是类似struct的头文件:

reflect.SliceHeader

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}
Run Code Online (Sandbox Code Playgroud)

reflect.StringHeader

type StringHeader struct {
        Data uintptr
        Len  int
}
Run Code Online (Sandbox Code Playgroud)

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

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

要获得某个任意值的实际(“递归”)大小,请使用Go的内置测试和基准测试框架。有关详细信息,请参见如何在Golang中获取变量的内存大小?

有关字符串,请参阅Golang中的字符串内存使用情况string值所需的完整内存可以这样计算:

var str string = "some string"

stringSize := len(str) + unsafe.Sizeof(str)
Run Code Online (Sandbox Code Playgroud)

  • @overexchange同样,正如我在回答中强调的那样,`unsafe.Sizeof()`返回的值不包括该值可能引用的任何内存。这意味着保存切片或字符串的实际字节所需的内存没有被覆盖。 (3认同)
  • @overexchange这取决于您如何定义“大小”。如果您还需要引用的/指向的大小,则它无效。 (2认同)
  • @overexchange是的,因为切片值或字符串值仅是标题。这是保存切片或字符串标头所需的内存。但是,如果您想知道分配/创建它们需要多少内存,则需要包括这些标头指向的数组的大小。 (2认同)