When we aren’t worried about storing any state, we don’t have to create an object in order to refer to a implementations in Go, or we can use an empty object.

Thanks to @dchapes for simplifying this solution for me — I love the Go community, and Reddit :)

Let’s say we want to describe types capable of encoding or decoding bytes to objects, we’ll call them Codecs:

type Codec interface {

Encode(w io.Writer, v interface{}) error

Decode(r io.Reader, v interface{}) error

}

We can then write a JSON Codec that simply wraps the capabilities of the standard library:

type jsonCodec struct{} func (jsonCodec) Encode(w io.Writer, v interface{}) error {

return json.NewEncoder(w).Encode(v)

} func (jsonCodec) Decode(r io.Reader, v interface{}) error {

return json.NewDecoder(r).Decode(v)

}

Since our jsonCodec type stores no state (it’s just a collection of methods really), it will be fine to use an empty jsonCodec wherever a Codec is needed. In fact, we don’t even bother specifying a receiver name in the first parenthesis — we just put func (jsonCodec) without a variable name.

Now we can provide an empty object for our users in the form of a variable, with a friendly name:

var JSON Codec = jsonCodec{}

This is a variable called JSON, of type Codec, that is an instance of the jsonCodec.

Interestingly, the size of the JSON variable is zero. Try it for yourself.

The only two types we have exported from our package are Codec and JSON, so our package remains neat and tidy.

We can call Encode and Decode directly on JSON:

err := JSON.Encode(w, obj)

err := JSON.Decode(r, obj)

And we can use JSON wherever a Codec is needed:

s := &Service{

Codec: JSON,

}

Using the above pattern also gives us compile time validation for free, that our jsonCodec type does indeed satisfy all the requirements of Codec.

See the discussion on Reddit about this post, has some interesting gems in it.