首页 > 解决方案 > GoLang - 内存分配 - []字节与字符串

问题描述

在下面的代码中:

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 数据所需的数据类型,我正在测试上面的示例代码以了解[]bytevsstring类型的内存分配。


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

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

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


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

标签: stringgomemorysize

解决方案


Both slices and strings in Go are struct-like headers:

reflect.SliceHeader:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

reflect.StringHeader:

type StringHeader struct {
        Data uintptr
        Len  int
}

The sizes reported by unsafe.Sizeof() are the sizes of these headers, exluding the size of the pointed arrays:

Sizeof takes an expression x of any type and returns the size in bytes of a hypothetical variable v as if v was declared via var v = x. The size does not include any memory possibly referenced by x. For instance, if x is a slice, Sizeof returns the size of the slice descriptor, not the size of the memory referenced by the slice.

To get the actual ("recursive") size of some arbitrary value, use Go's builtin testing and benchmarking framework. For details, see How to get memory size of variable in Go?

For strings specifically, see String memory usage in Golang. The complete memory required by a string value can be computed like this:

var str string = "some string"

stringSize := len(str) + int(unsafe.Sizeof(str))

推荐阅读