与我在C++中学到的类似,我认为是填充导致两个 struct 的实例大小不同.

type Foo struct {
    w byte //1 byte
    x byte //1 byte
    y uint64 //8 bytes
}
type Bar struct {
    x byte //1 byte
    y uint64 //8 bytes
    w byte// 1 byte
}
func main() {
    fmt.Println(runtime.GOARCH)
    newFoo := new(Foo)
    fmt.Println(unsafe.Sizeof(*newFoo))
    newBar := new(Bar)
    fmt.Println(unsafe.Sizeof(*newBar))
}

输出:

amd64
16
24
  • 定义 struct 成员时是否有经验法则可遵循?(如文字大小的升序/降序)
  • 有没有我们可以通过的编译时间优化,可以自动解决这个问题?
  • 或者我根本不应该担心这个?

推荐答案

目前没有编译时优化;在x64上,这些值被填充到8字节.

您可以手动排列 struct ,以最佳利用空间;通常是从大型到小型;例如,8个连续字节字段只使用8个字节,但是将单个字节填充到8字节对齐,考虑如下:https://play.golang.org/p/0qsgpuAHHp

package main

import (
    "fmt"
    "unsafe"
)

type Compact struct {
    a, b                   uint64
    c, d, e, f, g, h, i, j byte
}

// Larger memory footprint than "Compact" - but less fields!
type Inefficient struct {
    a uint64
    b byte
    c uint64
    d byte
}

func main() {
    newCompact := new(Compact)
    fmt.Println(unsafe.Sizeof(*newCompact))
    newInefficient := new(Inefficient)
    fmt.Println(unsafe.Sizeof(*newInefficient))
}

如果考虑到这一点,就可以优化 struct 的内存占用.

Go相关问答推荐

SEARCH On Conflict Clause不考虑乐观锁定版本

Go Net/http路由

Golang XML密钥名称冲突

GORM:一个表的两个外键

如何使用 html/template 在 golang 中运行一个范围内的范围

Go struct 匿名字段是公开的还是私有的?

Golang - POST 失败(NoSurf CSRF)

如何从 Go 中的 `HijackedResponse` 中删除 Cursor Position ANSI 转义码?

如何在模板中传递和访问 struct 片段和 struct

Go:从 ssl 证书中获取 'subject/unstructeredName' 的值

如何使用带有方法的字符串枚举作为通用参数?

通过环境变量配置 OTLP 导出器

go-libp2p - 从流中接收字节

使用innerxml在 Go 中编码 XML 是否仅适用于某些类型?

如何在 helm 中将字符串连接到 .AsConfig 的结果?

Golang invopop jsonschema 使用 if/then/else

没有堆栈跟踪的 go 程序崩溃是什么意思?

Golang 数据库/sql 与 SetMaxOpenConns 挂起

vs 代码调试 go 测试不通过标志

Golang 查询扫描未将查询正确扫描到 struct 中