Top Related Projects
Quick Overview
Fx is a dependency injection system for Go. It provides a set of tools and patterns for building modular, maintainable, and testable applications by managing the lifecycle of objects and their dependencies.
Pros
- Simplifies dependency management in large Go applications
- Encourages modular and testable code structure
- Supports both constructor and struct tag-based dependency injection
- Integrates well with existing Go code and libraries
Cons
- Introduces additional complexity for small projects
- Requires a learning curve to understand and use effectively
- May lead to increased compile times due to reflection
- Can make debugging more challenging due to indirect object creation
Code Examples
- Basic dependency injection:
package main
import (
"fmt"
"go.uber.org/fx"
)
type Greeter struct {
Name string
}
func NewGreeter() *Greeter {
return &Greeter{Name: "World"}
}
func (g *Greeter) Greet() {
fmt.Printf("Hello, %s!\n", g.Name)
}
func main() {
fx.New(
fx.Provide(NewGreeter),
fx.Invoke(func(g *Greeter) {
g.Greet()
}),
).Run()
}
- Struct tag-based injection:
package main
import (
"fmt"
"go.uber.org/fx"
)
type Config struct {
Port int
}
type Server struct {
fx.In
Config *Config `name:"serverConfig"`
}
func NewConfig() *Config {
return &Config{Port: 8080}
}
func main() {
fx.New(
fx.Provide(
fx.Annotated{
Name: "serverConfig",
Target: NewConfig,
},
),
fx.Invoke(func(s Server) {
fmt.Printf("Server running on port %d\n", s.Config.Port)
}),
).Run()
}
- Lifecycle management:
package main
import (
"context"
"fmt"
"go.uber.org/fx"
)
type Resource struct{}
func NewResource() *Resource {
return &Resource{}
}
func (r *Resource) Initialize(lc fx.Lifecycle) {
lc.Append(fx.Hook{
OnStart: func(context.Context) error {
fmt.Println("Resource initialized")
return nil
},
OnStop: func(context.Context) error {
fmt.Println("Resource cleaned up")
return nil
},
})
}
func main() {
fx.New(
fx.Provide(NewResource),
fx.Invoke((*Resource).Initialize),
).Run()
}
Getting Started
To start using Fx in your Go project:
-
Install Fx:
go get go.uber.org/fx
-
Import Fx in your main package:
import "go.uber.org/fx"
-
Define your dependencies and use
fx.New()
to create an application:func main() { fx.New( fx.Provide( NewConfig, NewDatabase, NewServer, ), fx.Invoke(StartServer), ).Run() }
-
Run your application and Fx will manage the dependency graph and lifecycle of your objects.
Competitor Comparisons
A standard library for microservices.
Pros of kit
- More comprehensive microservices toolkit with support for various transport protocols
- Extensive documentation and examples for different use cases
- Larger community and ecosystem of extensions
Cons of kit
- Steeper learning curve due to its extensive feature set
- More boilerplate code required for simple applications
- Heavier dependency footprint
Code Comparison
kit example:
func main() {
svc := service.New(logger, db)
endpoints := endpoint.New(svc, logger)
httpHandler := transport.NewHTTPHandler(endpoints, logger)
http.ListenAndServe(":8080", httpHandler)
}
fx example:
func main() {
fx.New(
fx.Provide(
NewLogger,
NewDB,
NewService,
NewHTTPHandler,
),
fx.Invoke(StartHTTPServer),
).Run()
}
kit focuses on explicit wiring of components, while fx uses dependency injection for a more concise setup. kit provides more flexibility in terms of transport protocols and middleware, but fx offers a simpler approach for smaller applications. Both libraries aim to improve the structure and maintainability of Go applications, with kit being more suited for complex microservices and fx for general-purpose dependency management.
Compile-time Dependency Injection for Go
Pros of Wire
- Compile-time dependency injection, catching errors early
- Generates code, avoiding runtime reflection for better performance
- Simpler syntax with less boilerplate compared to fx
Cons of Wire
- Requires a separate code generation step
- Less flexibility for runtime configuration changes
- Steeper learning curve for complex dependency graphs
Code Comparison
Wire:
func InitializeEvent() Event {
wire.Build(NewEvent, NewGreeter, NewMessage)
return Event{}
}
fx:
func main() {
fx.New(
fx.Provide(NewEvent, NewGreeter, NewMessage),
fx.Invoke(func(e Event) {
e.Start()
}),
).Run()
}
Wire focuses on compile-time dependency injection, generating code to wire dependencies. It requires a separate build step but catches errors early and avoids runtime reflection.
fx, on the other hand, uses runtime dependency injection, offering more flexibility for configuration changes. It has a more declarative syntax and integrates well with other Uber Go libraries.
Both tools aim to simplify dependency management in Go applications, but they take different approaches. Wire is better suited for projects prioritizing compile-time safety and performance, while fx excels in scenarios requiring runtime flexibility and integration with other Uber Go ecosystem components.
⚙️ A dependency injection toolkit based on Go 1.18+ Generics.
Pros of do
- Simpler API with less boilerplate code
- Supports generics, allowing for type-safe dependency injection
- Smaller codebase, potentially easier to understand and maintain
Cons of do
- Less mature and less widely adopted compared to fx
- Fewer advanced features and customization options
- Limited documentation and community support
Code Comparison
fx:
var module = fx.Module("example",
fx.Provide(
NewConfig,
NewLogger,
NewService,
),
fx.Invoke(Run),
)
do:
container := do.New()
container.Provide(NewConfig)
container.Provide(NewLogger)
container.Provide(NewService)
container.Invoke(Run)
Both fx and do are dependency injection frameworks for Go, but they differ in their approach and features. fx offers a more comprehensive solution with advanced features and extensive documentation, while do provides a simpler, more lightweight alternative with support for generics. The choice between the two depends on the project's complexity, team preferences, and specific requirements.
Package inject provides a reflect based injector.
Pros of inject
- Simpler API with fewer concepts to learn
- Lightweight and focused solely on dependency injection
- More flexible in allowing manual object creation and injection
Cons of inject
- Less feature-rich compared to fx's lifecycle management and module system
- Not actively maintained (archived repository)
- Limited support for advanced dependency resolution scenarios
Code Comparison
inject:
type App struct {
Name string `inject:""`
DB *sql.DB `inject:""`
}
var app App
injector := inject.New()
injector.Provide(&app)
injector.Provide(db)
injector.Populate()
fx:
type App struct {
Name string
DB *sql.DB
}
fx.New(
fx.Provide(
NewApp,
NewDB,
),
fx.Invoke(func(app *App) {
// Use app
}),
)
inject focuses on simple field injection, while fx uses constructor injection and offers more structured application composition. fx provides a more robust framework for managing dependencies and application lifecycle, whereas inject is a lighter-weight solution for basic dependency injection needs.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
:unicorn: Fx
Fx is a dependency injection system for Go.
Benefits
- Eliminate globals: Fx helps you remove global state from your application.
No more
init()
or global variables. Use Fx-managed singletons. - Code reuse: Fx lets teams within your organization build loosely-coupled and well-integrated shareable components.
- Battle tested: Fx is the backbone of nearly all Go services at Uber.
See our docs to get started and/or learn more about Fx.
Installation
Use Go modules to install Fx in your application.
go get go.uber.org/fx@v1
Getting started
To get started with Fx, start here.
Stability
This library is v1
and follows SemVer strictly.
No breaking changes will be made to exported APIs before v2.0.0
.
This project follows the Go Release Policy. Each major version of Go is supported until there are two newer major releases.
Stargazers over time
Top Related Projects
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot