Working with Scalar Data Types
1. Using Integer Types
| Type | Range | Wire | Best For |
| int32 | −2³¹ … 2³¹−1 | varint | Positive small ints |
| int64 | −2⁶³ … 2⁶³−1 | varint | IDs, timestamps |
| uint32 / uint64 | 0 … 2³² / 2⁶⁴ | varint | Counters, sizes |
Warning: int32/int64 encode negative numbers as 10 bytes. Use sint32/sint64 for negatives.
2. Using Fixed-Size Integers
| Type | Size | Best For |
| fixed32 | Always 4 bytes | Values frequently > 2²⁸ |
| fixed64 | Always 8 bytes | Hashes, large IDs |
| sfixed32/64 | 4 / 8 bytes signed | Predictable size for negatives |
3. Using Signed Integers
| Type | Encoding | Use When |
| sint32 | ZigZag → varint | Likely negative 32-bit |
| sint64 | ZigZag → varint | Likely negative 64-bit |
Example: Signed delta
message TempReading {
sint32 delta_celsius = 1; // often negative
}
4. Using Floating Point Types
| Type | Precision | Size |
| float | ~7 digits | 4 bytes |
| double | ~15 digits | 8 bytes |
Warning: Never use floats for currency. Use int64 minor units (cents) or a Money message.
5. Using Boolean Type
| Property | Value |
| Wire size | 1 byte (varint) |
| Default | false (not sent on wire) |
| Naming | Positive predicate: is_active, has_email |
6. Using String Type
| Property | Detail |
| Encoding | UTF-8, length-delimited |
| Max | Practically limited by message-size cap (default 4 MB client recv) |
| Invalid UTF-8 | Decoders reject |
7. Using Bytes Type
| Use | Why |
| Binary blobs | No UTF-8 validation overhead |
| Pre-encoded data | Images, signatures, encrypted payloads |
| Cryptographic keys | Avoid base64 round-trip |
8. Understanding Type Encoding
| Wire Type | Value | Types |
| VARINT | 0 | int*, uint*, sint*, bool, enum |
| I64 | 1 | fixed64, sfixed64, double |
| LEN | 2 | string, bytes, message, packed repeated |
| I32 | 5 | fixed32, sfixed32, float |
9. Choosing Appropriate Types
| Need | Type |
| DB primary key | string (UUID) or int64 |
| Money | int64 minor units + currency code |
| Timestamp | google.protobuf.Timestamp |
| Duration | google.protobuf.Duration |
| Enums | enum with UNSPECIFIED = 0 |
| Binary | bytes |
10. Understanding Default Values
| Behavior | Detail |
| Singular scalar at default | Omitted from wire |
| Field number conflict on default | Receiver sees default — looks the same |
| Workaround | Use optional or a wrapper type (e.g. google.protobuf.Int32Value) |