为什么 Go 不为结构比较指定填充内容?

  • 本文关键字:填充 比较 Go 结构 go
  • 更新时间 :
  • 英文 :


摘自Dave Cheney关于Go编译器生成的结构比较代码的文章(https://dave.cheney.net/2020/05/09/ensmallening-go-binaries-by-prohibiting-comparisons(:

填充

的存在是为了确保正确的字段对齐,虽然它确实占用了内存中的空间,但这些填充字节的内容是未知的。您可能会假设,作为 Go,填充字节始终为零,但事实证明并非如此 - 填充字节的内容根本没有定义。由于它们未定义为始终为某个值,因此执行按位比较可能会返回 false,因为分布在 S 的 24 个字节[以前定义的带有填充的结构]中的 9 个字节的填充可能不同。

Go 编译器通过生成所谓的相等函数来解决此问题。在这种情况下,S 的相等函数知道如何通过仅比较函数中的字段同时跳过填充来比较 S 类型的两个值。

编辑:相同的源声明struct {int64, int64}使用内存比较进行比较,而struct {int64, int8}由于填充而需要自定义函数,从而扩大生成的二进制文件。

为什么 Go 编译器不通过定义填充字节内容来解决这个问题,这样它就可以使用memcmp之类的东西进行比较?

编辑:归零或比较一个单词而不是一个字节是否有任何开销(例如:在上一个struct {int64, int8}示例中归零并比较 16 个字节而不是 9 个字节(?

从规范:

如果结构值

的所有字段都可比较,则结构值具有可比性。如果两个结构值对应的非空字段相等,则它们相等。

换句话说,结构相等不是简单的逐字节比较。它是使用每个字段的可比性/相等性规则进行的逐字段比较。

编辑:

即使填充被归零,许多结构仍然无法使用类似memcmp的东西直接进行比较。字符串和接口等类型由于其基础类型表示形式而无法与内存进行比较,即使它们在逻辑上是可比较的,并且根据规范可以相等。要了解此操作的实际效果,请查看 https://play.golang.org/p/lmu-THnWY3W。

如果你想看看结构相等是如何实现的,请查看源代码。

最新更新