Thanks for the suggestion.
I'll leave some detail here for posterity.
In case a single goroutine takes care of the decoding the problem can be solved with a io.LimitedReader. Just (re)set the max number of bytes before each call to Decode. This approach is nice because it is very trivial, it is less nice because it breaks with concurrent goroutines and because the resetting of the byte count is not encapsulated inside the ReadWriter interface.
The approach Rob suggested solves the concurrency and encapsulation problems nicely, but requires a (very limited) understanding of gob's format.
From gob documentation:
Finally, each message created by a call to Encode is preceded by an encoded unsigned integer count of the number of bytes remaining in the message. After the initial type name, interface values are wrapped the same way; in effect, the interface value acts like a recursive invocation of Encode.
How an unsigned integer is encoded:
An unsigned integer is sent one of two ways. If it is less than 128, it is sent as a byte with that value. Otherwise it is sent as a minimal-length big-endian (high byte first) byte stream holding the value, preceded by one byte holding the byte count, negated. Thus 0 is transmitted as (00), 7 is transmitted as (07) and 256 is transmitted as (FE 01 00).
Function to decode an uint: