> struct field alignment matches C (even without cgo)
The spec defines alignment for numeric types, but that's about it. There is nothing in the spec about struct layout. That is implementation dependent. If you are relying on a particular implementation, you are decidedly in unsafe territory.
> so any change to the default would break a lot of code.
The compiler can disable optimization on cgo calls automatically and most other places where it matters are via the standard library, so it might not be as much as you think. And if you still have a case where it matters, that is what this is for: https://pkg.go.dev/structs#HostLayout
That's good to know. I'm not making use of this assumption, but the purego package (came from ebitengine) does. It looks like they're aware of HostLayout [1] but I'm not sure how many other people have gotten the memo (HostLayout didn't exist before Go 1.23).
binary.Read/Write already uses reflect as far as I can tell, so it wouldn't matter in that case. There is an optimization for numeric values in there, which may be what you are thinking of? But they are specified in the spec and that's not what we're talking about anyway (and if an optimization really had to go, for whatever reason, it wouldn't be the end of the world).
Basically, binary.Read/binary.Write are capable of reading/writing struct values. The worry would be that, if the Go compiler reordered fields under the hood, the order may differ between writing the data and reading it back (especially across different versions of Go).
However, because these functions use reflection, they likely wouldn't be affected. While the in-memory layout of the struct fields might get reordered, presumably the reflection order would match the declaration order. Indeed, there is already an Offset field on the reflect.StructField type, and there is no statement anywhere I can find that such offsets must increase monotonically.
So, the fields would remain in declaration order when inspected with reflection, but their offsets could jump around within the struct, yet well behaved reflection-based code should be agnostic to this change.
This is very unfortunate, since most structs are never going to be passed to C, yet end up paying the tax anyway. They really should have made it opt-in.