Dependency Injection with fx
#Reading List
- Dependency Injection in Go using Fx Series
- Simplify dependency injection using Uber FX.
- go.uber.org/fx
- https://github.com/sumiet/medium_webserver_series
- FX.Modules
- https://www.youtube.com/watch?v=LDGKQY8WJEM
- https://blog.huyage.dev/posts/simple-dependency-injection-in-go/
#Code
Code from Dependency Injection in Go using Fx Series
series.
// - config.yaml -
// - config.go -
package main
type ApplicationConfig struct {
Address string `yaml:"address"`
}
type Config struct {
ApplicationConfig `yaml:"application"`
}
// - main.go -
package main
import (
"bytes"
"context"
"io"
"log"
"net/http"
"os"
"github.com/butuzov/sandbox/dependency-injection/fx/httphandler"
"go.uber.org/fx"
"go.uber.org/zap"
"gopkg.in/yaml.v3"
)
func main() {
os.Exit(run())
}
func run() int {
fx.New(
fx.Provide(ProvideConfig),
fx.Provide(ProvideLogger),
fx.Provide(http.NewServeMux),
fx.Provide(httphandler.New),
// invokers
fx.Invoke(registerHooks),
).Run()
return 0
}
func registerHooks(
lifecycle fx.Lifecycle,
logger *zap.SugaredLogger,
cfg *Config,
mux *httphandler.Handler,
) {
lifecycle.Append(
fx.Hook{
OnStart: func(context.Context) error {
go http.ListenAndServe(cfg.ApplicationConfig.Address, mux)
return nil
},
OnStop: func(context.Context) error {
return logger.Sync()
},
},
)
}
func ProvideLogger() *zap.SugaredLogger {
logger, _ := zap.NewProduction()
slogger := logger.Sugar()
return slogger
}
func ProvideConfig() *Config {
var buf bytes.Buffer
cnf := &Config{}
f, err := os.Open("config.yaml")
if err != nil {
log.Printf("config: %s", err)
return nil
}
defer f.Close()
if _, err := io.Copy(&buf, f); err != nil {
log.Printf("reading: %s", err)
return nil
}
if err := yaml.Unmarshal(buf.Bytes(), &cnf); err != nil {
log.Printf("yaml: %s", err)
return nil
}
log.Printf("%#v", cnf)
return cnf
}
// - server.go -
package httphandler
import (
"net/http"
"go.uber.org/zap"
)
// Handler for http requests
type Handler struct {
mux *http.ServeMux
log *zap.SugaredLogger
}
// RegisterRoutes for all http endpoints
func (h *Handler) registerRoutes() {
h.mux.HandleFunc("/", h.hello)
}
func (h *Handler) hello(w http.ResponseWriter, r *http.Request) {
h.log.Warn("request in")
w.WriteHeader(200)
w.Write([]byte("Hello World"))
h.log.Warn("request out")
}
func New(s *http.ServeMux, l *zap.SugaredLogger) *Handler {
h := Handler{s, l}
h.registerRoutes()
return &h
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.mux.ServeHTTP(w, r)
}