Mastering Dependency Injection in Go with Uber’s Fx Framework

This article explains the core concepts of dependency injection, introduces Uber’s Fx framework for Go, and provides step‑by‑step code examples that demonstrate how to register providers, manage application lifecycles, and use hooks for start‑up and shutdown logic.

FunTester
FunTester
FunTester
Mastering Dependency Injection in Go with Uber’s Fx Framework

Dependency Injection (DI) is a fundamental design pattern that improves code maintainability and testability. While Java developers often rely on Spring’s IoC container, Go lacks a built‑in DI framework, prompting the need for external solutions such as Uber’s fx library.

What is Uber Fx?

The fx framework simplifies DI and lifecycle management for Go applications. It offers a modular API including fx.Provide for registering constructors, fx.Invoke for executing functions, fx.In and fx.Out for struct‑based injection, and fx.Lifecycle with fx.Hook for start‑up and shutdown hooks.

Simple Application Startup

func main() {
    app := fx.New() // create an fx.App instance
    app.Run()       // run the fx.App instance
}

The fx.New function accepts a variadic list of Option values, which are typically providers or invocations that configure the application.

Registering Providers and Using Constructors

The following example shows how to define simple structs, provide constructors, and let fx wire them together. It also demonstrates integration with the zap logger.

package main

import (
    "go.uber.org/fx"
    "go.uber.org/zap"
)

func main() {
    app := fx.New(
        fx.Provide(NewTester, func() *Age { return &Age{Num: 18} }),
        fx.Provide(func() *zap.Logger { l, _ := zap.NewProduction(); return l }),
    )
    app.Run()
}

type Age struct { Num int }

type Tester struct { Log *zap.Logger; Age *Age }

func NewTester(age *Age, log *zap.Logger) *Tester { return &Tester{Age: age, Log: log} }

Here fx.Provide registers three constructors: one for Age, one for zap.Logger, and one for Tester. fx automatically resolves the dependencies and injects them when the application starts.

Managing Lifecycle with Hooks

To execute custom logic during start‑up and shutdown, define a function that receives fx.Lifecycle and the dependent components, then append a fx.Hook.

func register(lc fx.Lifecycle, t *Tester) {
    lc.Append(fx.Hook{
        OnStart: func(context.Context) error {
            t.Log.Info("Starting server")
            return nil
        },
        OnStop: func(context.Context) error {
            t.Log.Info("Stopping server")
            return nil
        },
    })
}

func main() {
    app := fx.New(
        fx.Provide(NewTester, func() *Age { return &Age{Num: 18} }),
        fx.Provide(func() *zap.Logger { l, _ := zap.NewProduction(); return l }),
        fx.Invoke(register),
    )
    app.Run()
}

The register function adds start‑up and shut‑down callbacks that log messages, illustrating how fx.Lifecycle and fx.Hook work together.

Typical Use Cases for fx.Lifecycle and fx.Hook

Resource Management : Open database connections on start and close them on stop.

Cache Initialization : Load caches when the app starts and clean them up on shutdown.

Message Queue Connections : Connect to queues at launch and disconnect gracefully.

Web Server Control : Start an HTTP server on start and perform graceful shutdown.

Scheduled Tasks : Launch background jobs on start and stop them when the app exits.

Logging and Monitoring : Emit logs and metrics at various lifecycle stages.

These patterns demonstrate how fx enables clean, modular, and testable Go applications.

Conclusion

After covering the basics of fx, readers should be able to build simple Go services with automated dependency injection and lifecycle handling, and can explore more advanced features in future articles.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentGolifecycle managementdependency-injection
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.