Angga Putra

Software Engineer

Field ordering in Go

I found this one through a PR comment.

At that time I was working on a feature for a service that felt important enough to make me extra careful. The logic was fine, the tests passed, and I thought I was already in the boring part of the review where people only point out naming or formatting.

Then one of the comments was about struct field ordering.

Struct field ordering can be optimized here. It affects memory alignment.

Senior Engineer, at tiket.com

It looked small enough to ignore if you did not know what it meant. The code worked. Nothing was broken. But I had never really thought about field order as something that could change how much memory a struct uses.

Seeing it

The example was simple enough that it made the point immediately.

type Bad struct {
	IsActive  bool
	TotalTime int64
	AvgScore  float32
}
 
type Good struct {
	TotalTime int64
	AvgScore  float32
	IsActive  bool
}

Both structs carry the same data. Same fields, same types, same meaning. The difference only shows up when you check how the compiler lays them out in memory.

fmt.Println(unsafe.Sizeof(Bad{}))  // 24
fmt.Println(unsafe.Sizeof(Good{})) // 16

I did not change the behavior at all, but the struct got smaller by ~33%.

Why it changed

Go aligns fields in a struct based on their type. If the order is awkward, the compiler adds padding so each field still lands on a boundary it likes.

That padding is invisible in the business logic, but it still costs memory. Here’s the visual.

Word 1Word 2Word 3Word 1Word 2Bad Struct (24 byte)Good Struct (16 byte)IsActiveTotalTimePaddingAvgScore

In the first version, the bool comes before larger fields. That forces extra space between fields. In the second version, the larger fields come first, so the layout wastes less room.

It was such a small fix that it almost felt unfair. I was used to thinking performance work meant rewriting logic, reducing queries, or changing algorithms. This one was just moving fields into a better order.

Resolving it

My first reaction was to do it by hand. I started grouping the wider fields first, then putting the smaller ones later.

That worked, but I also learned there was already a tool for this. The tool is called fieldalignment, and it points out structs that could be laid out more efficiently.

fieldalignment ./...

If I want it to apply the suggested reordering, it can do that too.

fieldalignment -fix ./...

That changed the lesson a bit for me. The useful part was not only knowing that field order matters. It was also knowing that I did not need to guess through every struct manually once I knew the right tool existed.

After that review

It was one of the first review comments that pushed me to look below the surface of the code a little more.

The feature was already correct. Users would not notice any difference from the outside. But the comment was still valid because good code is not only about getting the right result. Sometimes it is also about noticing the small things the runtime has to carry for you.