Why I like Go’s interfaces

Yan Cui

I help clients go faster for less using serverless technologies.

When I hear people talk about Go, a lot of the discussions focus on its concurrency features. Whilst it has a good concurrency story, the language landscape is currently filled with languages that have an equally good or better concurrency story – F#, Erlang, Elixir, Clojure, etc…

Personally, what I found really interesting from my time with Go was how its interfaces work. In short, interfaces do not need to be explicitly implemented – i.e. no implement keyword. Instead, interfaces are satisfied implicitly.

 

Duck Typing

In dynamic languages such as Python, you have the concept of Duck Typing.

“if it looks like a duck and quacks like a duck, it’s a duck”

Suppose you have a say_quack  function in Python which expects its argument to have a quack  method. You can invoke the function with any object so long it has the quack  method.

image

Duck typing is convenient, but without a compiler to catch your mistakes you are trading a lot of safety for convenience.

trade_off_1

 

What if there’s a way to get the best of both worlds?

In F#, this can be achieved through statically resolved type parameters:

image

But syntactically, statically resolved TP is kinda clunky and not the easiest to read. Go’s interfaces represent a more elegant solution in my view.

 

Implicitly Implemented Interface

In Go, suppose you have an interface for a Duck:

image

Any struct that has a Quack  method will implement the Duck  interface implicitly and can be used as a Duck.

image

(try it yourself here)

If you have another struct, Dog, which doesn’t have a Quack  method and you tried to use it as a Duck  then you’ll get a compile time error:

image

(try it yourself here)

so there, the convenience of duck typing with the safety of static checking!

trade_off_2

 

Beyond Convenience

The design for Go’s interface stems from the observation that patterns and abstractions only become apparent after we’ve seen it a few times.

So rather than locking us in with abstractions at the start of a project when we’re at the point of our greatest ignorance, we can define these abstractions as and when they become apparent to us.

When you create a new interface, you don’t have to go back and tag every implementation, which sometimes might not be possible if the implementation is owned by a 3rd party.

This makes Go interfaces incredibly cheap, and encourages you to create very granular, precise interface definitions.

 

All and all, even though I don’t enjoy writing code in Go (as you tend to write imperative style of code), I think there are some very interesting ideas and lessons to take from the language.

It’s also a very relevant language of our time, with some important products (ahem, Docker) having been written in Go.

It’s a very small language still, and its website does a good job in helping you get started. Take a tour of Go if you’re interested in learning more about the language.

 

Links


 

Whenever you’re ready, here are 4 ways I can help you:

  1. If you want a one-stop shop to help you quickly level up your serverless skills, you should check out my Production-Ready Serverless workshop. Over 20 AWS Heroes & Community Builders have passed through this workshop, plus 1000+ students from the likes of AWS, LEGO, Booking, HBO and Siemens.
  2. If you want to learn how to test serverless applications without all the pain and hassle, you should check out my latest course, Testing Serverless Architectures.
  3. If you’re a manager or founder and want to help your team move faster and build better software, then check out my consulting services.
  4. If you just want to hang out, talk serverless, or ask for help, then you should join my FREE Community.

 


12 thoughts on “Why I like Go’s interfaces”

  1. In F# I’ll probably have used an interface rather than statically resolved TP to be honest, makes for more readable and idiomatic .Net code.

    .Net interfaces though, are much more expensive in that you have to go around and tag every type that you want to use as that interface (and sometimes you can’t because it might be a BCL class or defined in a 3rd party library).

    With interfaces (whose members should make sense in its local scope) you also tend to overfit for the purpose of the functions that depend on them.

    And then there’s naming… the name of the interface should probably make sense in the context of its implementers rather than the functions that depend on them, otherwise what happens when you rename those functions or remove them? Would the interface names still make sense to whoever looking at the implementing types?

    All and all, interfaces in .Net are still quite a strong form of coupling, but that’s probably more a discussion around the expression problem.

    With Asp.Net vNext they’re experimenting with the idea of assembly neutral interfaces (http://davidfowl.com/assembly-neutral-interfaces-implementation/) which I hear is inspired by Go’s interfaces. But it’s only available on a particular runtime (Asp.net vNext) and seems to solve a different problem.

  2. Thanks! What’s your opinion on TypeScript’s interface and duck typing? It is quite similar to Go’s interface.

  3. You have a typo in your second Go listing:

    duck = Bird{}
    duck.Quack() // ~quack ~quack

    should be:

    duck = Daisy{}
    duck.Quack() // ~quack ~quack

    The type `Bird` isn’t declared anywhere.

  4. I haven’t looked at TypeScript yet, that’s good to know though. Will let you know once I’ve had a chance to spend some time with TypeScript.

  5. true, that’s a good point, thanks for that, will update the code snippets when I get home

  6. there, changed the code snippets to be consistent with the others, thanks again for bringing it up

  7. Pingback: F# Weekly #20, 2015 | Sergey Tihon's Blog

Leave a Comment

Your email address will not be published. Required fields are marked *