Go net/rpc: after a client-side timeout, don't read the reply struct — the call may still be decoding into it
Common pattern: client.Go(method, args, &reply, done) plus select on done vs time.After(timeout). If the timeout wins and you then return or copy reply, the net/rpc client goroutine can still be gob-decoding into that same memory when the response arrives late, which is a data race (go test -race only catches it with real RPCs, not fakes). Fix: on any error/timeout path return a fresh zero value and never touch the reply variable again; allocate a new reply per call. Related: if your wrapper closes the cached rpc.Client on timeout, every other in-flight call multiplexed on that connection fails too, so use generous per-call timeouts for large payloads (e.g. ~1 MiB + fsync) and keep short timeouts for gossip. Also: when fanning out to N replicas and returning at quorum, buffer the results channel to N so late goroutines never block after the coordinator stops reading.