diff options
Diffstat (limited to 'content/json-rpc.article')
-rw-r--r-- | content/json-rpc.article | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/content/json-rpc.article b/content/json-rpc.article new file mode 100644 index 0000000..fc0541f --- /dev/null +++ b/content/json-rpc.article @@ -0,0 +1,62 @@ +# JSON-RPC: a tale of interfaces +27 Apr 2010 +Tags: json, rpc, technical +Summary: How to use the net/rpc package's interfaces to create a JSON-RPC system. +OldURL: /json-rpc-tale-of-interfaces + +Andrew Gerrand + +## + +Here we present an example where Go's [interfaces](https://golang.org/doc/effective_go.html#interfaces_and_types) +made it easy to refactor some existing code to make it more flexible and extensible. +Originally, the standard library's [RPC package](https://golang.org/pkg/net/rpc/) +used a custom wire format called [gob](https://golang.org/pkg/encoding/gob/). +For a particular application, we wanted to use [JSON](https://golang.org/pkg/encoding/json/) +as an alternate wire format. + +We first defined a pair of interfaces to describe the functionality of the +existing wire format, +one for the client, and one for the server (depicted below). + + type ServerCodec interface { + ReadRequestHeader(*Request) error + ReadRequestBody(interface{}) error + WriteResponse(*Response, interface{}) error + Close() error + } + +On the server side, we then changed two internal function signatures to +accept the `ServerCodec` interface instead of our existing `gob.Encoder`. Here's one of them: + + func sendResponse(sending *sync.Mutex, req *Request, + reply interface{}, enc *gob.Encoder, errmsg string) + +became + + func sendResponse(sending *sync.Mutex, req *Request, + reply interface{}, enc ServerCodec, errmsg string) + +We then wrote a trivial `gobServerCodec` wrapper to reproduce the original functionality. +From there it is simple to build a `jsonServerCodec`. + +After some similar changes to the client side, +this was the full extent of the work we needed to do on the RPC package. +This whole exercise took about 20 minutes! +After tidying up and testing the new code, +the [final changeset](https://github.com/golang/go/commit/dcff89057bc0e0d7cb14cf414f2df6f5fb1a41ec) was submitted. + +In an inheritance-oriented language like Java or C++, +the obvious path would be to generalize the RPC class, +and create JsonRPC and GobRPC subclasses. +However, this approach becomes tricky if you want to make a further generalization +orthogonal to that hierarchy. +(For example, if you were to implement an alternate RPC standard). +In our Go package, we took a route that is both conceptually simpler and +requires less code be written or changed. + +A vital quality for any codebase is maintainability. +As needs change, it is essential to adapt your code easily and cleanly, +lest it become unwieldy to work with. +We believe Go's lightweight, composition-oriented type system provides a +means of structuring code that scales. |