Dependency Injection the Go Way

Go dependency injection is a bit different but necessary, but Go's code is so much cleaner, it's the only language I love using.

Go is a very good language. I use it for all of my side stuff. From websites to command line tools. Working with database, and even got the beginnings of a 2D game going on it.

To describe the need for and history of dependency injection would need a few chapters. So I'll just show how I did it in Go, with a little precursor to why I need it!

In my project, altarschedule.com, I have developed it and run it locally with Docker. There are live systems and other things that I don't want to touch. Like the live production database that is storing all of the data. The other thing that it does is sends emails, and I don't want to actually be sending emails, using up my quota, for testing.

Database Injection

Typically with my Go web projects that use Google's Datastore (document database), I will develop it just using .json files locally. This gets me the same functionality but does end up adding quite a bit to the timeline, as I essentially have to write data access twice. But it's very useful for basically having the same functionality without the overhead of having to connect with the cloud database. Here's how I'll go about that.

First, I'll define my data types. These are shared between the .json version of the database, and the Datastore version.

As you can see, this is the basic User type, and I set attributes (field tags in Go) for both datastore and json.

Next I'll define the interface that deals with this data (and other related data)

In this particular application, there are a lot of other data that is related to a user, but here is the basic idea with the first set of methods in the interface.

After implementing the interface for both “databases” (json files in one instance, datastore in the other), I simply let the application know which database to use with an environment variable. This is easily set in both Docker and in AppEngine.

Docker:

AppEngine:

You can see the precursor to the next part, deciding whether to use SendGrid or AppEngine to send emails. If both are false, it sends to the console. And there was an update where sendgrid won't be necessary anymore.

Email Injection

Here is the code for the three separate types of email senders. Very simple

And getting a new sender is as simple as this:

And the implementations for loggerSender and appEngineSender! So clean :)
 

I think the dependency injection part of languages like C# can be a little bit nicer with not having to write code to decide which one to use, but Go's code is so much nicer in general that I can't really recommend the other languages.

Since Go compiles to a statically linked binary, it pretty much makes it impossible to have a configuration based dependency injection. However, it's also probably a security risk where anyone can inject anything into executing code. It's a minor convenience to be able to do that, so I don't really consider it when deciding to use Go.