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

时间:2020-05-11 14:41:46

标签: go

Dave Cheney的文章中介绍了Go编译器(https://dave.cheney.net/2020/05/09/ensmallening-go-binaries-by-prohibiting-comparisons)生成的结构比较代码:

存在填充以确保正确的字段对齐,并且尽管它确实占用了内存空间,但是这些填充字节的内容是未知的。您可能以为Go填充字节始终为零,但事实并非如此-填充字节的内容未定义。由于未将它们定义为始终为某个特定值,因此按位比较可能会返回false,因为九个填充字节分布在S [先前定义的填充结构] 的24个字节中一样。

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

编辑:同一来源指出struct {int64, int64}是使用内存比较进行比较的,而struct {int64, int8}由于填充而需要自定义函数,从而放大了生成的二进制文件。

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

编辑:对一个字而不是一个字节进行清零或比较是否有任何开销(例如:在上一个struct {int64, int8}示例中对零个字节而不是9进行清零和比较)?

1 个答案:

答案 0 :(得分:4)

来自spec

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

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

编辑:

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

如果您想了解如何实现结构相等,请查看source code

相关问题