Procyon|Docs
ComponentsRegistration

Scopes

Choose singleton or prototype creation behavior.

Components are singleton-scoped by default. The container creates one instance and reuses it for later resolutions.

register.go
func init() {
	component.Register(NewUserService)
}

Singleton scope is the right default for services, repositories, clients, and framework extensions.

Prototype scope

Use prototype scope when each resolution should create a new instance.

request_state.go
func init() {
	component.Register(NewRequestState, component.AsPrototype())
}

type RequestState struct {
	Values map[string]string
}

func NewRequestState() *RequestState {
	return &RequestState{Values: make(map[string]string)}
}

You can also set the scope directly:

register.go
component.Register(
	NewRequestState,
	component.WithScope(component.PrototypeScope),
)

Custom scopes

Framework extensions can implement component.Scope when instance reuse needs a custom rule.

scope.go
type Scope interface {
	// Resolve returns an existing scoped instance or creates one with fn.
	Resolve(ctx context.Context, name string, fn component.FactoryFunc) (any, error)

	// Remove deletes the scoped instance for the given component name.
	Remove(ctx context.Context, name string) error
}

Custom scopes are registered through the container's ScopeRegistry. They are advanced extension points; most application components should use singleton or prototype.

Scope guidance

  • Use singleton for shared, concurrency-safe services.
  • Use prototype for short-lived mutable state.
  • Avoid storing request-specific state in singleton components.
  • Keep custom scope strings for framework extensions that know how to handle them.