Skip to main content

FAQ

Answers to common questions about samber/do. For terminology, see the glossary; for a broader introduction, see Dependency Injection in Go.

Does samber/do use reflection?

No. samber/do resolves and injects services using Go 1.18+ generics, so type checks happen at compile time. The only exception is do.InvokeStruct, an opt-in helper that uses reflection to populate struct fields tagged with `do:""`.

How is samber/do different from uber/fx?

uber/fx resolves dependencies at runtime via reflection (through uber/dig) and adds an application lifecycle on top. samber/do resolves services through generics instead of reflection, and ships its own lifecycle primitives (health checks, graceful shutdown, hooks) without pulling in dig or fx as dependencies. See the full do vs uber/fx comparison.

Can I use samber/do without generics?

No, samber/do requires Go 1.18 or later because its entire API — Provide, Invoke, Override, As — is built on generic type parameters. There is no reflection-based fallback for older Go versions.

How do I mock a service in tests?

Clone the injector with Clone() or CloneWithOpts(), then call do.Override (or do.OverrideNamed / do.OverrideValue) to replace a service with a test double before invoking it. For whole packages, ship a second Package variant exposing mocks behind the same interfaces — see package loading.

Does samber/do detect circular dependencies?

Yes. Services must be invoked in a Directed Acyclic Graph (DAG); samber/do tracks the invocation chain through internal virtual scopes and returns an error as soon as a cycle is detected, instead of deadlocking or overflowing the stack. Use service dependencies to inspect a suspicious chain.

Is samber/do production-ready?

Yes. samber/do v2 ships built-in health checks, dependency-aware parallel shutdown, lifecycle hooks, and a debug Web UI, and has no breaking changes planned before v3. See the v1 to v2 upgrade guide if you're on an older version.

How do I gracefully shut down services?

Call injector.Shutdown() or injector.ShutdownOnSignals(syscall.SIGTERM, os.Interrupt) on the root scope. Every service implementing the Shutdowner interface is stopped in reverse invocation order, and child scopes shut down recursively.

What is a scope in samber/do?

A scope is a module with restricted visibility: it can see services from its ancestor scopes but not from its siblings. Applications typically keep a root scope for shared infrastructure and dedicated child scopes for business logic.