Nugget Post: Golang: RPC server/client implementation

As part of my efforts to learn golang, I attempted to write a simple RPC server / client implementation. Between gobs (see my previous post) and the RPC implementation, golang makes it very easy to build a distributed system where servers and client share not only data via gobs, but also methods and functions via RPC.

It turns out RPC isn’t difficult at all, but to me at least, it required a slight mindshift. Because of my prevalent use of REST APIs, I went into this thinking the methods defined on the server could accept arbitrary arguments, then the method itself would use those arguments to build new objects, increase counters, and do whatever other work is needed. This is not so. The most valuable nugget I learnt during this experiment is listed up top on the golang RPC documentation page:

Only methods that satisfy these criteria will be made available for remote access; other methods will be ignored:
- the method is exported.
- the method has two arguments, both exported (or builtin) types.
- the method's second argument is a pointer.
- the method has return type error.
In effect, the method must look schematically like
func (t *T) MethodName(argType T1, replyType *T2) error

 

First of all, RPC works by “exporting” methods that are defined on types. Note that the methods need to be exported – that means must start with a capital letter people!

Second, every method defined can have only two arguments. The second argument is reserved for the reply that is sent back to the client, which means the “input” to the method must be contained within the first argument. This in turn means that the first argument is nearly always a struct, enabling you to pass multiple input values encapsulated within a single variable. Unless, of course, you define a method which only needs a single input, like in the snippet below (see full code on github page):

// create a function named "PersonGetter"
func (p *Person) PersonGetter(id int, per *Person) error {
	*per = PersonMap[id]
	return nil
}

In the above, we are fetching an element from a map, determined by a single input, so the first argument need not be a struct. Also note that in the snippet above, the function returns type error, as per the specs laid out above.

Since golang enforces a certain signature for the RPC exported methods,  it makes you as a developer be more structured. If one peruses the code from the various examples, you will note that while the method definitions reside solely on the server, the data structs and types  that describe the input and reply are mostly shared on both the client and server, and this helps to keep a certain amount on continuity between the client and server.

View my full code on githubhttps://github.com/dvas0004/learning/tree/master/golang/myown/rpc

References: