Go中的RPC是否具有某种缓存?

yesterday I played arround with RPC in go and had a behaviour I couldn't understand.

I wrote a simple RPC server, which runs in a VM, listens for connections and serves a single method for fibonacci calculation. A RPC client on the local machine asks the server every second for fibonacci(n), where n is (currentSecond*fixedMultiplicator), so i can produce at least slightly different loads.

So, in a for loop, the client will request 60 different values in 60 seconds and then start over. The RPC dial is outside this loop, so the connection is somewhat persistent.

When I kill the server, lets say, after 10 seconds, the client will throw an error because it can't send anything to the now missing server. So far, works as planned.

Now what made me think: When I kill the server after 61 seconds, the client keeps printing out the correct results for ever request, although the server is missing and could not answer a request. I even shut down the VM of the server, so the server IP isn't even in the network any more. While being kind of interesting, this behavior could be harmful for a real application (depending on what you are developing).

Any ideas?

// ############
// # RPC SERVER

err := rpc.Register(service.Object)
// errorcheck

rpc.HandleHTTP()
l, e := net.Listen("tcp", ":1301")
// errorcheck
go http.Serve(l, nil)


// ############
// # RPC CLIENT

client, err := rpc.DialHTTP("tcp", "192.168.2.111:1301")
// errorcheck

var divCall *rpc.Call

for {
    <-time.After(time.Duration(1 * time.Second)):

    n := time.Now().Second() * 90000000
    log.Debug("n=", n)

    args := &services.FibonacciArgs{N: n}
    var reply int
    divCall = client.Go("Fibonacci.Calculate", args, &reply, nil)

    go func() {
        replyCall := <-divCall.Done
        r := replyCall.Reply.(*int)
        log.Debug("reply: ", r)
    }()
}

Answer

After running the code on Linux and Windows, I noticed different results. On Linux, the reply will always be the appropriate zero value (in my case 0). On Windows on the other hand it the reply seems to be cached.

The way to go is @cnicutar's hint. Check error value after the RPC call and handle stuff accordingly. Never trust the reply blindly.

You don't check for errors in your code:

divCall = client.Go("Fibonacci.Calculate", args, &reply, nil)

go func() {
    replyCall := <-divCall.Done

    // -- Must check replyCall.Error here --.

    r := replyCall.Reply.(*int)
    log.Debug("reply: ", r)
}()

That said, I think the behavior is peculiar and there might be more to this.