The I64 wire type is the eight-byte twin of I32, backing fixed64, sfixed64, and double. Today you decode and encode those eight little-endian bytes and pin the bit pattern of the double 1.0.
Decode and encode a fixed64 value as eight little-endian bytes.
The I64 wire type is I32’s bigger sibling: exactly eight bytes,
little-endian, no length prefix, backing fixed64, sfixed64, and double. The
decode and encode are the same low-byte-first loop as fixed32 with eight iterations
instead of four. Encoding the integer 1 gives a single 0x01 followed by seven
zero bytes, a good sanity check that the least-significant byte really does come
first.
A double reinterprets those eight bytes as an IEEE 754 double-precision number.
The value 1.0 is the bit pattern 0x3FF0000000000000; written little-endian the
nonzero bytes land at the high end, ... 0xF0 0x3F, which is a useful shape to
recognize when you eyeball a hex dump. With fixed32 and fixed64 in hand you can now
read every numeric scalar protobuf defines; only strings and bytes remain.
func ReadFixed64(b []byte) uint64 {var v uint64for i := 0; i < 8; i++ { v |= uint64(b[i]) << (8 * i) } // low byte firstreturn v}func AppendFixed64(buf []byte, v uint64) []byte {for i := 0; i < 8; i++ { buf = append(buf, byte(v>>(8*i))) }return buf}// a double is these same 8 bytes reinterpreted (math.Float64frombits)