Documentation
¶
Index ¶
Constants ¶
const ( ServiceLifetimeContainer = "container" ServiceLifetimeScoped = "scoped" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Container ¶
type Container interface {
Registrar
Resolver
OverrideService
ScopeManager
Names() []string
Close() error
}
type ContainerCarrier ¶ added in v2.13.0
type ContainerCarrier interface {
Container() Container
}
ContainerCarrier is implemented by resolvers that can name the container behind them. A process-lifetime service that defers work past the resolution that built it — a lazily-dialed pool, a registry that opens on first use — replays that work through the container, not through the resolution context it was constructed with: a resolution context is single-threaded and dies with its scope, while the container is the process-lifetime, lock-guarded half the deferred work actually needs. The container itself satisfies the shape by answering itself.
type OverrideOption ¶ added in v2.13.0
type OverrideOption func(option *OverrideOptions)
type OverrideOptions ¶ added in v2.13.0
type OverrideOptions struct {
/* ClosedWithScope hands the installed value to the scope's teardown. An override belongs by default to whoever installed it and outlives the scope — the http kernel installs the request logger and goes on using it to report the scope's own close failure — so a caller that built the value FOR this scope and has nowhere else to close it says so here. */
ClosedWithScope bool
}
OverrideOptions carries what an override declares beyond the value itself.
type OverrideService ¶
type OverrideServiceWithOptions ¶ added in v2.13.0
type OverrideServiceWithOptions interface {
OverrideInstanceWithOptions(serviceName string, value any, options ...OverrideOption) error
MustOverrideInstanceWithOptions(serviceName string, value any, options ...OverrideOption)
OverrideProtectedInstanceWithOptions(serviceName string, value any, options ...OverrideOption) error
MustOverrideProtectedInstanceWithOptions(serviceName string, value any, options ...OverrideOption)
}
OverrideServiceWithOptions is the optional companion of OverrideService. It is a separate interface so the four signatures of OverrideService never move: an installed override is the oldest thing in this package and every framework caller of it predates options.
type RegisterOption ¶
type RegisterOption func(option *RegisterOptions)
type RegisterOptions ¶
type RegisterOptions struct {
AlsoRegisterType bool
TypeRegistrationIsStrict bool
/* ReplacesContainerService admits a SCOPED registration whose name — or whose registered type — the container already claims; the container-level registration paths do not read it. Without it the collision is refused at the point it is made: a scoped service silently shadowing a container singleton is a wiring mistake whose symptom appears one lifetime away from its cause. With it, the scoped registration answers inside a scope and the container's keeps its own lifetime outside one. Declared where nothing collides yet, the waiver stands: a container registration of the same name arriving later is admitted without declaring anything itself.
It admits substitution, not decoration. A scoped provider that resolves the name it is replacing re-enters itself, and the resolution is reported as the circular dependency it is; a decorator has to take the decorated service under its own name. */
ReplacesContainerService bool
}
type Registrar ¶
type Registrar interface {
Register(serviceName string, provider any, options ...RegisterOption) error
MustRegister(serviceName string, provider any, options ...RegisterOption)
}
type Scope ¶
type Scope interface {
Resolver
ScopedRegistrar
OverrideService
Close() error
}
type ScopeManager ¶
type ScopeManager interface {
NewScope() Scope
RegisterScoped(serviceName string, provider any, options ...RegisterOption) error
MustRegisterScoped(serviceName string, provider any, options ...RegisterOption)
}
ScopeManager makes scopes and declares what they will hold. The two belong together: a scope does not exist until a request arrives, and the framework is what creates one, so the services a scope owns have to be declared at boot by whatever will be making the scopes rather than on a scope that is not there yet.
A registration made here reaches every scope created afterwards; the ones already running keep the plan they were created with. Scope carries the same verbs for the rare case of adding a service to one live scope.
type ScopedRegistrar ¶ added in v2.13.0
type ScopedRegistrar interface {
RegisterScoped(serviceName string, provider any, options ...RegisterOption) error
MustRegisterScoped(serviceName string, provider any, options ...RegisterOption)
}
ScopedRegistrar registers services whose lifetime is one scope: built lazily on the first Get through that scope, held for as long as it lives, closed when it closes. The root container never sees them, and two scopes resolving the same name never meet.
It is deliberately not a Registrar, and it does not embed one. The two registrations differ only in lifetime, and a provider handed to the wrong one is a mistake the compiler cannot see when both spell the same verb: a container provider registered as scoped is rebuilt and torn down once per request without ever failing. Go interfaces are structural, so a marker type carrying Registrar's own method set would be satisfied by a container registrar and would catch nothing in either direction. The verb at the call site is therefore the declaration, and the two method sets are kept disjoint so a registrar handed to the wrong hook is a compile error rather than a convention.
type ServiceDescription ¶ added in v2.13.0
ServiceDescription is what a container can say about a registration without running its provider: the name, which lifetime owns it, whether an instance already exists, and the type — read from the built instance when there is one, from the provider's declared return type otherwise. It exists so an introspection command can list a container without building it.