Go Interfaces and Delegation Pattern
https://nathany.com

Go Interfaces and Delegation Pattern

First published on Medium.

If you’re coding in Go but have not yet dabbled into interfaces, you’re missing out. Interfaces are core to the Go language, and they can be used to organize your code to prevent import cycles.

Note: If you already know interfaces, skip down to Broker and Delegate Pattern.

Interfaces in Go

Interfaces are not classes. They exist in language like Java to aid the lack of multiple inheritance (which is a good lack).

There’s a sound amount of counter-movement to class-based OOP nowadays. If you have worked with classes in any language, you might have felt some redundancy. Classes can be viewed as overkills or an inside-out view from the development perspective (and also a Darwinian one). A new and refreshing outside-in view is composition.

But I’m here to write about interfaces, specifically in Go. I assume you have used inheritance in Go with embedding in structs:

type struct


type struct






This is a composition pattern?—?a pattern in which one identity is in a IS-A or HAS-A relationship with another by acquiring the properties or the identities of it. Here we add some favorite to the cat and it will return a sound as a response.

func
append
return


But wait! A dog, a reindeer, or a sloth should be able to be given a favorite food and respond with gratitude too! The Cat is a bourgeois prick, as it always were!

It turns out that Animal itself isn’t a being?—?it is a category or a concept. In this case we might use an interface instead of a struct.

Have you ever heard, “If it walks and swims like a duck, it is probably one” or the famous quote from Deng Xiaoping, “It doesn’t matter whether a cat is white or black, as long as it catches mice.”?

Well, it does make sense to categorize something by the abilities to do something, since actions define beings.

 

Interfaces are the “brokers” of abilities. A being is said to comply to an interface to become a being of some kind. Here is a duck analogy in interface.

type interface





If a being can walk, swim and quack, it’s a Duck. Simple as that. Here are three different breeds of ducks modeled as structs:

type struct type struct type struct


Each breed may take different amount of time to cover the walking or swimming distance given, or some may even quack out loud, but it is definitely a Duck just the same, provided it implements the Duck interface.

func
// speed is 1 ft per second


return
func

func


// A bluerunner quacks once between walking

return func

func




return
func


The Swim methods are spared for brevity, but you get the idea. Now as all the ducks are “registered”, any function can receive any of them as an argument.

func

Now, however a duck quack, it can shares one function to execute. This is a powerful pattern of code organization and application modeling.

If a being can walk, swim and quack, it’s a Duck (interface).

Broker or Delegate Pattern

One scenario I’m using is the broker / delegation pattern, which was inspired by Obj-C and Swift programming in iOS. Basically, the concept is a unit of code should be as portable and encapsulated as possible with little or no knowledge of the external code that is using it. If something is considered not within the responsibility of the unit, it should delegate the task to another unit which is better at delegation and coordination.

This is especially useful in avoiding import cycles, which can almost always happen as your code grows. When you import an external package into your project’s package, the cycle import does not happen because the external package is kept intact and never imports your package back.

However, when you deal with imports between your created packages within your project, you can accidentally create an import cycle.

The solution I used was to make sure a package can never be imported directly by another package, and that a code in a package should be as encapsulated as possible. I introduced a “Delegate” struct for each package which implements a broker interface of its own.

This way, a package is always imported via its broker while it import other package’s brokers. Instead of importing a package and using its public function like this:

package import

func


We can let the packageA’s abroker deals with it by wrapping packageA’s Delegate struct with a broker interface and just import the broker.

package import

var func

This is what abroker might look like:

package import

type

func
return

And for packageA itself, it needs a Delegate struct to instantiate itself as well as make all public functions methods to make the struct implements the ABroker interface:

package type func

This way all packages are encapsulated and only the brokers are allowed to deal with package imports directly. It can be seen as redundant and repetitive until you know that since go 1.5 there’s a go:generate command that you can use to run a pre-hook code and generate an interface for each package before running the main code.

If you like my write up, be sure to follow my blog Joe Chasinga or twitter @jochasinga or better, offer me a job where I can crack Go all day!

要查看或添加评论,请登录

Pan Chasinga的更多文章

  • How to Set Better Goals in 2025

    How to Set Better Goals in 2025

    Ever wonder why your New Year resolutions never stuck around? Our brain is an ancient machine that's been, for over…

  • An Open Letter to School

    An Open Letter to School

    This is a letter to all the schools I went through and spent time in demoralization, spiritual abuses, and…

  • The Comfort of being Unstable

    The Comfort of being Unstable

    Two weeks ago, before my trip to Thailand ended, I decided to visit Chiang Rai, the most northern city in the country…

  • I Caught the Earlybird Train

    I Caught the Earlybird Train

    A small commute victory that teaches me not to give up. It was 6.

    1 条评论
  • How to not Lose Mind

    How to not Lose Mind

    It's easy to lose your mind juggling between career, work, family, and personal life. It's stressful because regardless…

  • Digging Tunnel with a Spoon

    Digging Tunnel with a Spoon

    There are moments when an inevitable question arise to any of us, "Should I keep doing this"? Doubt is as constant as…

  • Embracing Constraints

    Embracing Constraints

    Life is all about constraints and restrictions. Since the very second we were born into this world, we have been…

  • How Roles killed Mastery (and Passion)

    How Roles killed Mastery (and Passion)

    Before there were engineers, architects, designers, and inventors, there were master builders. Before the World Wars…

    2 条评论

社区洞察

其他会员也浏览了