大家好,我是煎鱼。
在 Go 这一门编程语言中,我们时常会看到一些 Go 面试题或结构体的知识讲解,主要是针对内存对齐这一块的知识点。
这次 Go1.23 新版本中也针对这块进行了一些补全,分享给大家,一起学习和进步!
背景
Go 在对于结构体(struct)的布局规则描述得相当简略。在现实环境中,大多数都是由需要准备面试的同学、感兴趣的同学研究后分析在社区内分享出来。
但在实践中,由于结构体在极少数情况下需要与平台 API 进行交互,Go 的实现被严格限制,必须遵循平台的布局和对齐规则。
当这些规则与 Go 的默认设置不一致时,例如:ppc64le 平台上,float64 字段的平台对齐方式与 Go 默认的对齐方式不同,就可能引发兼容性问题。
这种情况迫使 Go 在那些约束条件与其它平台常见的情况不同的平台上做出权衡,或者可能引发问题,阻碍了可以节省内存和提高垃圾回收效率的字段重新排序优化。
Go1.23 新标准库 structs
本次 Go1.23 新增了一个标准库 structs,与 strings、bytes 和 slices 几个库并行,本次有着特殊的使用作用。
这个新库现阶段只有一个东西,那就是核心的 HostLayout 结构体:
package structs
// HostLayout, as a field type, signals that the size, alignment,
// and order of fields conform to requirements of the host
// platform and may not match the Go compiler’s defaults.
type HostLayout struct {}
HostLayout 用于声明和指定结构体采用主机的内存布局方式。当结构体包含 HostLayout 类型的字段时,其在内存中的布局将遵循主机的期望,一般与主机的 C 应用二进制接口(ABI)保持一致。
值得注意的是,HostLayout 仅影响其所在的结构体本身的布局,而不影响结构体内部其他结构体字段的布局,也不会影响包含这种特殊布局结构体的其他结构体。
本次新增加的 HostLayout 将会作为字段类型使用,该字段在使用时建议命名为下划线("\_"),并放在结构体定义的最开始位置。
具体的用法例子,如下代码:
// 通过 HostLayout 指定结构体布局方式
type HasHostLayout struct {
_ structs.HostLayout
// 煎鱼正在干些什么...
...
SomeField SomeType
}
// 正常,无指定结构体布局方式
type SomeType struct {
a, b int8
x int32
c, d int8
}
var x SomeType
var y HasHostLayout
var ap []*SomeType = []*SomeType{&x, &y.SomeField}
...
用法的重点:放在在结构体字段定义的第一个位置、使用 _ structs.HostLayout
进行初始化声明。以此即可指定结构体采用主机的内存布局方式。
总结
Go 的结构体内存布局是不少人研究和参考的对象之一,因为很多同学希望能够拿到最节省内存性能的方式。
但是实际上 Go 缺省的布局方式在不同的 OS 平台中,也有水土不服的。软件工程没有银弹。
本次 Go1.23 新增的 structs.HostLayout
有效的给 Go 程序员自定义结构体的内存布局打开了一个 “后门”,能够根据自己真实的主机平台情况进行定制化的结构体内存决策。
- 本文作者:煎鱼
- 公众号:脑子进煎鱼了
- 联系方式(微信号):cJY0728(加我拉你进技术交流群)
文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。