...
Don’t use the
required
the field. The required field raises a decoding error if the field is not present in the message, which restricts the backward and forward compatibility of a proto message. For cockroach specifically, sending messages between two crdb nodes with different binaries becomes treacherous.Use the
gogoproto.nullable
option so the compiled field type is the type itself instead of a pointer. We use this option because we want our generated proto structs to look and feel like regular go structs-- specifically, we follow the convention that the absence of the value is represented as the 0 value of the type, instead of a null pointer. Note that by default go primitive types are compiled to the type itself. There are two exceptions to this recommendation:If you really need to distinguish between the zero value vs absent, then don’t set this option. Further, if you want a pointer to a primitive type, set
gogoproto.nullable=false
.If the type of the field is very large, i.e. another message type with lots and lots of fields, and if we'll be passing instances of the containing type around often. Then the one time alloc and just copying addr to pass it can actually be cheaper. But this too is pretty rare (I imagine it might hold for Descriptor and RequestUnion but not many others).
Don’t use the
optional
field. As described here, it allows the user to distinguish between the zero value and if the field is absent. If you need this, work withgogoproto.nullable
invocation so the compiled field is nullable.Avoid
types.Any
andjson
types like the plague. They are very hard to decode while inspecting them in a debug zip.
Gotchas
For protobufs on performance critical paths, beware that empty fields can have non zero space overhead when marshalled. To ensure these fields are truly empty in the encoded message, use Radu’s fancy omitEmpty field.
...