Go mascot in small bee hive blocks showing modules
Source: Golang Weekly

Writing Fx Modules

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

Level Up Coding
Published in
4 min readJan 26, 2021

--

In the previous article, we explored how we can convert a manually wired HTTP web server into a DI-based web server using the Fx library. Now once we have that in place, our next step is to add functionalities to our server .i.e business logic. But before we jump into that, we need to first understand how to write modules for our Fx Server. These modules will act as building blocks for our application.

What is a module?

Generically speaking, a module is a piece of program that is independent and interchangeable, such that each module contains everything necessary to execute only one aspect of the desired functionality. (Source: Wikipedia).

When we write a line of code, we achieve a mini-goal with that. This might be our business logic, trimming trailing spaces from a string, or maybe getting the current system time, etc. Each of these cases is unique and can exist independently and has a meaning to it, so shall we go ahead and create a module out of it? Well, I don’t think so.

We should be thoughtful while defining modules. An ideal scenario to create a module would be when you want to encapsulate some behavior such that it is reusable across the application and at times outside the application as well. Generally, this behavior is exposed outside the module using an interface. For example, a few good use cases to create a module would be the logging module, metric module, authorization module, etc.

Please make sure you understand the difference between a library, a framework & a module.

What is an Fx Module?

As we saw in the last article, that all Fx does is that it injects an object into another object. And in order to inject object A into object B, it needs to have object A inplace beforehand. So where does it gets object A in the first place from?

Confusing…right?

Let’s try to simplify it, when Fx creates a new object (we call it OBJ1, hereafter) it looks up for the dependencies that OBJ1 needs.

Case1: No dependencies required, OBJ1 is created in the application context.

Case 2: Fx finds the needed dependencies in the application context, injects them and OBJ1 is created.

Where did all of this happen? It happened inside a fx.provide call, which in turn is part of a module whose responsibility is to create OBJ1 and provide it to the application context when the New method is called in the Fx lifecycle. (Fx Documentation)

Fx is designed on the concepts of Modular programming. Whenever you write a line of code in an application that is achieving DI using Fx, it is always a part of some module(unless manually wired). You already wrote code inside a module when you converted your application into an Fx application.

Our First Fx Module: LoggerFx

We will try to add logging into the web server which we have built so far. For this, we will use zap as a logging library(built by uber). We add a file called loggerfx.go

// ProvideLogger to fx
func ProvideLogger() *zap.SugaredLogger {
logger, _ := zap.NewProduction()
slogger := logger.Sugar()

return slogger
}

// Module provided to fx
var Module = fx.Options(
fx.Provide(ProvideLogger),
)

and then update the main.go to this:

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

func registerHooks(
lifecycle fx.Lifecycle, mux *http.ServeMux, logger *zap.SugaredLogger,
) {
lifecycle.Append(
fx.Hook{
OnStart: func(context.Context) error {
logger.Info("Listening on localhost:8080")
go http.ListenAndServe(":8080", mux)
return nil
},
OnStop: func(context.Context) error {
return logger.Sync()
},
},
)
}

We are all set to run the application which will serve the “Hello World” response on “/” route. But this time we also see the log Listening on localhost:8080 on our console.

go run main.go

Voila! That’s how simple it is to write a module in Fx. Please find the code here on Github.

Please note that we used the Zap library, inside the Fx framework to create the LoggerFx module. Hope that helps you understand the differences in those three terminologies even better.

Now, the task for you to get hands-on experience with Fx Modules is to convert the HTTP handler into a module. Happy Coding!

In the next article, we will explore Remote Procedure Calls and add an RPC handler module to our service.

RPC Explained

Coding Fun Fact: The word computer “bug” was inspired by a real bug. It was founded by Grace Hopper in 1947.

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.

--

--

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