본문으로 건너뛰기
cccskills
무료GitHub에 공개

golang-uber-fx

Build Go services with uber-go/fx by connecting components and managing startup and shutdown. This skill covers dependency injection, which supplies components with what they need, plus reusable modules, signal handling, logging, and tests with substitute dependencies.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Golang application framework using uber-go/fx — fx.New, fx.Provide, fx.Invoke, fx.Module, fx.Lifecycle hooks, fx.Annotate (name/group/As), fx.Decorate, fx.Supply, fx.Replace, fx.WithLogger, and signal-aware Run(). Apply when using or adopting uber-go/fx, when the codebase imports `go.uber.org/fx`, or when wiring services with fx.New. For raw DI without lifecycle, see `samber/cc-skills-golang@golang-uber-dig` skill.

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • Connect components in a Go service with fx
  • Manage server startup and graceful shutdown
  • Organize application features into reusable modules
  • Test services with substitute dependencies

포함된 파일(5)

  • SKILL.md11.1 KB
  • evals/evals.json12.5 KB
  • references/advanced.md5.3 KB
  • references/recipes.md8.6 KB
  • references/testing.md4.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Persona: You are a Go architect building a long-running service with fx. You wire the graph at the composition root, push lifecycle into hooks instead of init(), and treat modules as the unit of reuse.

Using uber-go/fx for Application Wiring in Go

Application framework combining a reflection-based DI container (built on uber-go/dig) with a lifecycle, module system, signal-aware run loop, and structured event logging. For long-running services where boot order, graceful shutdown, and modular composition matter.

Official Resources:

This skill is not exhaustive — refer to library documentation and code examples for more information:

  • For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig), preferred over Context7 for Go package facts.
  • To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls).
  • Context7 remains a fallback for docs not indexed on pkg.go.dev.
go get go.uber.org/fx

fx vs. dig

fx is built on top of dig and shares the same reflection-based container engine. The DI primitives (Provide, Invoke, In/Out structs, named values, value groups) are identical — fx.In/fx.Out are re-exports of dig.In/dig.Out.

What fx adds on top:

Concerndigfx
DI container✅ dig.New()✅ (embedded)
Lifecycle hooks❌✅ fx.Lifecycle OnStart/OnStop
Module system❌✅ fx.Module with scoped decorators
Signal-aware run loop❌✅ app.Run() blocks on SIGINT/SIGTERM
Structured event logging❌✅ fx.WithLogger / fxevent
Startup/shutdown timeout❌✅ fx.StartTimeout / fx.StopTimeout

Choose fx for long-running services (HTTP servers, workers, daemons) — lifecycle and signal handling are mandatory there, and modules make large service graphs manageable.

Choose raw dig when you need wiring without a framework: CLI tools, libraries that expose a container to callers, test harnesses, or embedding DI into an existing app that manages its own lifecycle. See samber/cc-skills-golang@golang-uber-dig skill.

The Application

import "go.uber.org/fx"

app := fx.New(
    fx.Provide(NewLogger, NewDatabase, NewServer),
    fx.Invoke(RegisterRoutes),
)
app.Run() // blocks until SIGINT/SIGTERM, then runs OnStop hooks

Boot stages: fx.New validates types (constructors do not run); app.Start(ctx) runs each fx.Invoke and fires OnStart hooks in topological order; main blocks on app.Done(); app.Stop(ctx) fires OnStop hooks in reverse order. Default timeout is 15 seconds — override with fx.StartTimeout / fx.StopTimeout.

Provide and Invoke

fx.New(
    fx.Provide(NewLogger, NewDatabase, NewServer),  // lazy
    fx.Invoke(RegisterRoutes, StartMetricsExporter), // always run during Start
)

fx.Provide registers constructors; fx.Invoke is the trigger — without an Invoke (directly or transitively) referencing a type, its constructor never runs.

Lifecycle Hooks

Inject fx.Lifecycle and append hooks. Constructors should return quickly; long-running work belongs in OnStart.

func NewHTTPServer(lc fx.Lifecycle, log *zap.Logger, cfg *Config) *http.Server {
    srv := &http.Server{Addr: cfg.Addr}

    lc.Append(fx.Hook{
        OnStart: func(ctx context.Context) error {
            ln, err := net.Listen("tcp", srv.Addr)
            if err != nil { return err }
            go srv.Serve(ln)         // blocking work in a goroutine
            return nil
        },
        OnStop: func(ctx context.Context) error {
            return srv.Shutdown(ctx)
        },
    })
    return srv
}

Both callbacks receive a context bounded by StartTimeout/StopTimeout — respect cancellation. OnStart must return quickly — spawn a goroutine for blocking work; otherwise startup hangs and dependent hooks never fire.

fx.StartHook / fx.StopHook / fx.StartStopHook adapt simpler signatures (no context, no error, or both):

lc.Append(fx.StartStopHook(srv.Start, srv.Stop))   // matched pair

Parameter and Result Objects

fx re-exports dig's dig.In / dig.Out as fx.In / fx.Out. Use them when a constructor has 4+ dependencies, or when you need name/group/optional tags.

type ServerParams struct {
    fx.In

    Logger *zap.Logger
    DB     *sql.DB
    Cache  *redis.Client     `optional:"true"`
    Routes []http.Handler    `group:"routes"`
}

func NewServer(p ServerParams) *Server { /* ... */ }

fx.Annotate

fx.Annotate wraps a constructor to add tags or interface bindings without a fx.Out struct. Prefer it for ergonomic name/group/As bindings:

fx.Provide(
    fx.Annotate(NewPrimaryDB, fx.ResultTags(`name:"primary"`)),
    fx.Annotate(NewPostgresDB, fx.As(new(Database))),    // expose interface
    fx.Annotate(NewUserHandler,
        fx.As(new(http.Handler)),
        fx.ResultTags(`group:"routes"`),
    ),
)

Value Groups

Many constructors, one consumer slice — typical for routes, health checks, metrics collectors:

type RouteResult struct {
    fx.Out
    Handler http.Handler `group:"routes"`
}

type ServerParams struct {
    fx.In
    Routes []http.Handler `group:"routes"`
}

Append ,flatten (group:"routes,flatten") to unwrap a slice instead of nesting it. Order is not guaranteed — provide an explicit ordered slice when sequence matters.

fx.Module

fx.Module groups providers, invokes, and decorators under a name. Modules scope decorators to themselves and their children — a logger renamed in fx.Module("db", ...) only appears renamed for code inside that module.

var DatabaseModule = fx.Module("database",
    fx.Provide(NewConnection, NewUserRepository),
    fx.Decorate(func(log *zap.Logger) *zap.Logger {
        return log.Named("db")
    }),
)

func main() {
    fx.New(
        fx.Provide(NewConfig, NewLogger),
        DatabaseModule,
        HTTPModule,
    ).Run()
}

Treat each module as a small library that can be lifted into another app — its public surface is the types it Provides.

For fx.Supply/fx.Replace/fx.Decorate, optional deps, custom logging, manual lifecycle, and Quick Reference, see advanced.md.

Best Practices

  1. Keep main() thin — providers, modules, and a single Run(). Push real work into modules so each can be tested in isolation.
  2. Use lifecycle hooks instead of init() or goroutines launched from constructors — Start/Stop ordering depends on graph topology, but init() goroutines do not, which leads to races and leaks.
  3. OnStart must return promptly — long work goes in a goroutine inside the hook. A blocking OnStart hangs the rest of the boot.
  4. Respect ctx.Done() in hooks — a hook that ignores cancellation is reported as a timeout failure but its goroutine continues, leaking resources.
  5. Group by module, not by layer — a module owns the providers, lifecycle, and decorators for one concern (HTTP, DB, metrics).
  6. Use fx.Annotate for tags rather than wrapping a constructor in an fx.Out struct — keeps the constructor reusable outside fx.
  7. Replace fx.Provide with fx.Supply for pre-built values (config, command-line flags). Shorter, signals intent.
  8. Validate the graph in CI by booting under fx.New(...).Err() — catches missing providers and cycles before deploy.

Common Mistakes

MistakeFix
Long-running work directly in OnStartSpawn a goroutine inside OnStart; the hook itself must return quickly so dependent hooks can run.
fx.Provide something that should be fx.SupplyPre-built values (config, secrets) belong in fx.Supply — clearer and avoids a no-op constructor.
Module decorator leaking to siblingsDecorate inside fx.Module(...) — decorators flow only to descendants. A top-level fx.Decorate is global.
Group order assumedGroups are unordered. If order matters, provide an ordered slice from one constructor.
Constructors with side effectsSide effects belong in OnStart — constructors should be cheap and pure-ish, since they may run concurrently and lazily.
Forgotten fx.InvokeWithout an Invoke (or downstream consumer), constructors never run. Add at least one Invoke per app.

Testing

Use go.uber.org/fx/fxtest to integrate fx with *testing.T (failures call t.Fatal, RequireStop registers as t.Cleanup). fx.Populate(&target) pulls values out of the graph; fx.Replace swaps real dependencies for fakes. Full patterns in testing.md.

Further Reading

  • advanced.md — Supply/Replace/Decorate, optional deps, custom event logging, manual lifecycle, full Quick Reference
  • recipes.md — full HTTP service with database/metrics, background workers with graceful drain, multiple impls of the same interface, manual lifecycle for CLI embedding
  • testing.md — fxtest patterns, fx.Replace, fx.Populate, isolated lifecycle tests, CI graph validation

Cross-References

  • → See samber/cc-skills-golang@golang-uber-dig skill for the underlying container, dig.In/dig.Out, and DI without lifecycle
  • → See samber/cc-skills-golang@golang-dependency-injection skill for DI concepts and library comparison
  • → See samber/cc-skills-golang@golang-samber-do skill for a generics-based alternative without reflection
  • → See samber/cc-skills-golang@golang-google-wire skill for compile-time DI (no runtime container)
  • → See samber/cc-skills-golang@golang-structs-interfaces skill for interface design patterns
  • → See samber/cc-skills-golang@golang-context skill for context propagation in OnStart/OnStop hooks
  • → See samber/cc-skills-golang@golang-testing skill for general testing patterns

If you encounter a bug or unexpected behavior in uber-go/fx, open an issue at https://github.com/uber-go/fx/issues.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Measure Go performance by writing benchmarks, examining CPU and memory profiles, and comparing repeated runs with benchstat. Use the results to assess code changes, detect slowdowns in CI, and investigate production performance.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Compare performance before and after a code change
  • Investigate CPU usage and memory allocations
  • Detect performance regressions in CI
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

Build, extend, or review Go command-line tools with clear commands, flags, and configuration priorities. It guides output formats, exit codes, shell completion, cancellation, and tests so tools behave predictably in scripts and terminals.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Build a Go command-line tool with subcommands
  • Combine flags, environment variables, and configuration files
  • Review output and exit codes for use in scripts
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

Make Go code easier to read by reviewing line breaks, variable declarations, branching, function parameters, and file organization. Provides concrete style guidance for implementation, code reviews, and project standards where formatting tools alone cannot judge clarity.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Reviewing Go code for readability
  • Simplifying nested branches and complex conditions
  • Improving long function signatures and calls
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

Design and review concurrent Go code with clear goroutine ownership, shutdown paths, and error handling. Choose channels, locks, or atomic operations to protect shared data, and structure worker pools with controlled concurrency and cancellation.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Design goroutine shutdown and cancellation
  • Choose channels or mutexes for concurrent code
  • Protect shared maps and counters
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

Design how Go requests carry cancellation signals, time limits, and request metadata through application layers. Helps investigate work that continues after cancellation, choose suitable context types, and separate background tasks from the request lifecycle.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Reviewing context propagation from HTTP handlers to database calls
  • Investigating missing cancellation and lingering timers
  • Keeping background work running after a request ends
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

Set up or improve GitHub Actions pipelines for Go projects. Configure automated tests, code checks, vulnerability scans, dependency update bots, releases, and Docker publishing, with workflow templates and repository settings that control permissions and merge requirements.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Set up automated tests and code checks for Go
  • Add vulnerability scanning to a pipeline
  • Configure dependency update bots
samber/cc-skills-golang3.6천2026년 10월 1일 업데이트

samber의 스킬 모두 보기

이 스킬의 문제 신고