Image for post
Image for post

Dependency Injection in Go using Fx

This article is part of the series GoLang: Building a Web Server

Sumit Agarwal
Jan 23 · 4 min read

As professionals, we should never stop learning. Learning is the one true way to ensure we stay in demand and continue delivering value to our customers. Doctors, lawyers, and scientists are all highly respected professionals and all focus on continuously learning. Why should programmers be different?

Hence, continuing where we left in the previous article. Once we have a basic HTTP server in GoLang up and running, the next step is to build the base for the project so that we can write more and more code easily to cater to varied use cases of the service.

A software design pattern that implements inversion of control for resolving dependencies is known as Dependency Injection(or DI hereafter). In dependency injection, a ‘dependency’ is an object that can be used (service) and ‘injection’ is the passing of a dependency to a dependent object or a client that would use it. Dependency Injection is a subset of Inversion of Control (IOC)…

The above-mentioned definition is something which you have read multiple times at multiple places, yet somehow it doesn’t stick. So here’s a simpler version of it:

Dependency injection is a pattern for object composition. A parent object provides all the dependencies required to the child object.

where:

  1. The parent is the object that instantiates and configures the child object it uses.
  2. The child is the component that is designed to be passively instantiated. I.e. it is designed to use whatever dependencies are provided by the parent and does not instantiate its own dependencies.

There are basically 3 types of Dependency Injection, namely:

  1. Constructor Injection
  2. Setter Injection
  3. Interface-based Injection

According to official documentation published by Uber, Fx is an application framework for Go that:

  1. Makes dependency injection easy.
  2. Eliminates the need for global state and func init().

Fx uses the constructor injection pattern, let’s try to understand how exactly it makes dependency injection easy in Go.

I strongly recommend you to go over the Fx documentation before reading further.

In order to keep things simple, we will try to convert the HTTP server from the previous article into an Fx App.

  1. The first step is to install the library via go get go.uber.org/fx.
  2. Edit the main.go with the initializer of an Fx App. If you run this using go run main.go you will have a basic Fx Server running with nothing to serve.
func main() {
fx.New().Run()
}

3. Now we will provide the HTTP serve Mux to the application by adding it to the New . We need to provide this to the application context so that it can be injected into our HTTP handler.

func main() {
fx.New(
fx.Provide(http.NewServeMux),
).Run()
}

4. Update the HTTP handler code as per the Fx spec so it can be provided into the application context. The updated looks like this:

package httphandler

import "net/http"

// Handler for http requests
type Handler struct {
mux *http.ServeMux
}

// New http handler
func New(s *http.ServeMux) *Handler {
h := Handler{s}
h.registerRoutes()

return &h
}

// RegisterRoutes for all http endpoints
func (h *Handler) registerRoutes() {
h.mux.HandleFunc("/", h.HelloWorld)
}
// HelloWorld handler which recieves the user request
func (h *Handler) HelloWorld(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("Hello World"))
}

Yes, you are right, nothing has changed. It’s completely the same as the code we wrote for our manually wired server, and that’s the beauty of Fx.

5. The last and final step is to start our listener, for this we will leverage the Fx Lifecycle Hooks. We will go ahead and update the main.go file to as below:

func main() {
fx.New(
fx.Provide(http.NewServeMux),
fx.Invoke(server.New),
fx.Invoke(registerHooks),
).Run()
}

func registerHooks(
lifecycle fx.Lifecycle, mux *http.ServeMux,
) {
lifecycle.Append(
fx.Hook{
OnStart: func(ctx context.Context) error {
go http.ListenAndServe(":8080", mux)
return nil
},
},
)
}

We are all set to run the application which will serve the “Hello World” response on “/” route.

go run main.go

Please find the code here on Github

I do understand that this might not look like a huge achievement from what we did in the manually wired server, and might be confusing at the first glance. How and where are things getting instantiated? What on earth are hooks? What exactly does the fx.New(something).Run() do? …..and many more questions.

But, trust me as we move forward with our web server development series you are going to realize what value does a good DI framework adds to your project. Although there are many upsides of DI, there are few downsides as well:

  1. Dependency injection creates clients that demand configuration details to be supplied by construction code. This can be difficult when obvious defaults are available.
  2. Dependency injection can make code difficult to trace (read) because it separates behavior from construction. This means developers must refer to more files to follow how a system performs.
  3. It requires more upfront development effort.

Now with dependency injection explored and basics of Fx covered. In the next article, we will try to learn the fundamentals of Fx Modules. We will also try to add these basic building blocks of a web server in our demo HTTP server and see how Fx Modules makes our life easy during the whole process.

Uber Engineering Blog on Youtube explaining DI and Fx

Coding Fun Fact: The first programmer in the world was a woman. Her name was Ada Lovelace and she worked on an analytical engine back in the 1,800’s.

Request: Please add your valuable feedback in the comments, that would really help me improve the quality of content and bring it in-line with your expectations.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Sumit Agarwal

Written by

I am a software developer at heart who likes to travel and has a profound interest in design, art, and literature.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Sumit Agarwal

Written by

I am a software developer at heart who likes to travel and has a profound interest in design, art, and literature.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store