I needed to pass structured measurements between two copies of a test program. Text was easy to inspect but tedious to parse, and writing a private binary format felt like volunteering to maintain archaeology.

The experimental Go library includes gob, which encodes typed values as a stream. In my current snapshot the package is imported simply as gob; its location and API may change before the language settles.

The sender is pleasantly small:

type Sample struct {
    Host  string
    Load  int
    Times []int64
}

enc := gob.NewEncoder(conn)
err := enc.Encode(Sample{"buildbox", 7, times})
if err != nil {
    return err
}

The receiver creates a decoder and supplies a destination value. Gob sends type information, then values using those types. Repeated values do not need to describe the complete structure each time, which makes a long-lived stream a better fit than many one-value connections.

Exported fields are the useful ones here. Private implementation details stay private, and fields are matched by name rather than by their physical offset in memory. That gives the decoder room to tolerate some structural evolution. It is not permission to change everything and hope.

I tried adding a field to the sender while leaving the old receiver alone. The old side ignored what it did not know. I then removed a field the receiver expected and got its zero value. That behavior is convenient for rolling experiments, provided zero has a sensible meaning.

Gob is Go-specific. I would not choose it for a public protocol consumed by C, Python, or an unknown implementation five years from now. Nor would I treat bytes emitted by today’s weekly snapshot as an archival format without tests against future toolchains.

For two cooperating Go programs built from a recorded snapshot, it removes a great deal of dull code. The mechanism is type description plus streamed values, not a dump of process memory, so pointers and machine layout are not being smuggled onto the wire. That is the right abstraction for this tool. The candid caveat is in the title: I am using it now, while keeping the protocol boundary small enough to replace later.