di

package module
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2024 License: MIT Imports: 10 Imported by: 0

README

godi

ci workflow

This library is an attempt to bring to Go a DI container requires as little action as possible from the user. You just need to define your services and the library will handle dependencies on its own, as much as possible. Whenever there's any ambiguity, you'll have to resolve it yourself.

This library takes heavy inspiration an excellent DI component of PHP Symfony framework.

Features

  • Service definition
  • Automatic and manual dependency resolution
  • Post-construct method invocation
  • Service aliases
  • Lazy/Eager instantiation
  • Cached/uncached services
  • Public/private services
  • Service tagging
  • Dependency graph validation and helpful errors
  • Programmatic control and container automation through compiler passes
  • Dependency graph visualization
  • Test mode (dependency overrides)
  • Service definitions from a config file

Installation

go get -u github.com/michalkurzeja/godi

Usage

Let's define some types that we'll want to wire using our DI container.

package main

type Foo struct{}

func NewFoo() Foo { return Foo{} }

type Bar struct {
	Foo Foo
}

func NewBar(foo Foo) Bar { return Bar{Foo: foo} }

type Baz struct {
	param string
}

func NewBaz(param string) Baz { return Baz{param: param} }

Now we can set up the container:

package main

import di "github.com/michalkurzeja/godi"

func main() {
	// Create a new container builder.
	builder := di.New()

	// Add services. Dependencies are resolved automatically.
	c, err = builder.Services(
		di.SvcT[Foo](NewFoo),
		di.SvcT[Bar](NewBar),
		// We need to manually provide the value of `Baz.param` because it's not in the container.
		di.SvcT[Baz](NewBaz).
		    Args(di.Val("my-string")),
	).Build()
	_ = err // If something is wrong, we will find out here!

	// We can now get our services from the container!
	foo := di.MustGet[Foo](c)
	bar := di.MustGet[Bar](c)
	baz := di.MustGet[Baz](c)
}

Global container

If you only need a single instance of container, you can use the package dig instead, which operates on a package-level container:

package main

import "github.com/michalkurzeja/godi/dig"

func main() {
	// Add services right away. The container is already there!
	_ = dig.AddServices(
		di.SvcT[Foo](NewFoo),
	).Build()

	foo := dig.MustGet[Foo]()
}
Inferred types

If you don't want to specify the types of your services, you can use the di.Svc function. It will figure out the types of your services based on the type returned by the given provider function.

package main

import "github.com/michalkurzeja/godi/dig"

func main() {
	_ = dig.AddServices(
		di.Svc(NewFoo),
	).Build()

	foo := dig.MustGet[Foo]()
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	DefaultPublic    = false
	DefaultLazy      = true
	DefaultShared    = true
	DefaultAutowired = true
)

Defaults for Definition properties. Change them to change the default configuration of services. These can be overridden per Definition.

Functions

func Get

func Get[T any](c Container, opts ...OptionsFunc) (T, error)

Get returns a service from the container and ensures its type.

func GetByTag added in v0.3.0

func GetByTag[T any](c Container, tag TagID) ([]T, error)

GetByTag returns all services from the container that have the given tag.

func Has added in v0.3.0

func Has[T any](c Container, opts ...OptionsFunc) bool

Has returns true if the container has a service with the given ID.

func Initialised added in v0.3.0

func Initialised[T any](c Container, opts ...OptionsFunc) bool

Initialised returns true if the service has been initialised, i.e. if the container currently holds the instance of that service.

func MustGet

func MustGet[T any](c Container, opts ...OptionsFunc) T

MustGet is like Get but panics if an error occurs.

func MustGetByTag added in v0.3.0

func MustGetByTag[T any](c Container, tag TagID) []T

MustGetByTag is like GetByTag but panics if an error occurs.

func Print added in v0.3.0

func Print(c Container, w io.Writer) error

Print prints the contents of the container to the given writer.

Types

type Alias added in v0.3.0

type Alias struct {
	// contains filtered or unexported fields
}

Alias represents an additional ID for a service. Any number of aliases can be created for a single service. Services may be referenced by their ID or any of their aliases.

func NewAlias added in v0.3.0

func NewAlias(aliasID, target ID) Alias

NewAlias creates a new alias. NewAlias("foo", "bar") aliases service "bar" as "foo".

func NewAliasT added in v0.3.0

func NewAliasT[A any](target ID) Alias

NewAliasT creates a new alias. The target ID is derived from the type parameter. NewAliasT[Foo]("bar") aliases service "bar" as "Foo".

func NewAliasTT added in v0.3.0

func NewAliasTT[A, T any]() Alias

NewAliasTT creates a new alias. The target and alias IDs are derived from the type parameters. NewAliasTT[Foo, Bar]() aliases service "Bar" as "Foo".

func (Alias) ID added in v0.3.0

func (a Alias) ID() ID

func (Alias) Target added in v0.3.0

func (a Alias) Target() ID

type Argument added in v0.3.0

type Argument interface {
	fmt.Stringer
	Type() reflect.Type
	// contains filtered or unexported methods
}

Argument represents a dependency that can be resolved by the container. Service factory functions and methods calls use Argument objects. Arguments can be either values, references or collections of tagged services.

type ArgumentBuilder added in v0.3.0

type ArgumentBuilder struct {
	// contains filtered or unexported fields
}

ArgumentBuilder is a helper for building arguments. It is used by the DefinitionBuilder to define arguments for a service factory and method calls.

func Ref

func Ref[T any](id ...ID) *ArgumentBuilder

Ref returns a new argument builder for a Reference.

func Tagged added in v0.3.0

func Tagged[T any](tag TagID) *ArgumentBuilder

Tagged returns a new argument builder for a TaggedCollection.

func Val

func Val(v any) *ArgumentBuilder

Val returns a new argument builder for a Value.

func Zero added in v0.3.2

func Zero() *ArgumentBuilder

func (*ArgumentBuilder) Build added in v0.3.0

func (b *ArgumentBuilder) Build() Argument

func (*ArgumentBuilder) Idx added in v0.3.0

Idx sets the index of the argument. E.g. Idx(1) will set the argument as the second argument of a function.

type Builder added in v0.3.0

type Builder struct {
	// contains filtered or unexported fields
}

Builder is a helper for building a container. It offers a fluent interface that incorporates other helpers to make the process of setting up the container easy and convenient for the user. This is the recommended way of building a container.

func New

func New() *Builder

New creates a new Builder. This is the recommended entrypoint to the godi library.

func (*Builder) Aliases added in v0.3.0

func (b *Builder) Aliases(aliases ...Alias) *Builder

func (*Builder) Build added in v0.3.0

func (b *Builder) Build() (Container, error)

func (*Builder) CompilerPass added in v0.4.0

func (b *Builder) CompilerPass(stage CompilerPassStage, priority int, pass CompilerPass) *Builder

func (*Builder) Functions added in v0.7.0

func (b *Builder) Functions(functions ...*FunctionDefinitionBuilder) *Builder

func (*Builder) Services added in v0.3.0

func (b *Builder) Services(services ...*DefinitionBuilder) *Builder

type CompilerPass added in v0.3.0

type CompilerPass interface {
	Compile(builder *ContainerBuilder) error
}

CompilerPass is a component of the compiler that can inspect and modify the container.

func NewInterfaceResolutionPass added in v0.3.0

func NewInterfaceResolutionPass() CompilerPass

type CompilerPassFunc added in v0.3.0

type CompilerPassFunc func(builder *ContainerBuilder) error

func NewAliasValidationPass added in v0.3.0

func NewAliasValidationPass() CompilerPassFunc

NewAliasValidationPass returns a compiler pass that validates all aliases. It ensures that they point to existing service definitions.

func NewAutowirePass added in v0.3.0

func NewAutowirePass() CompilerPassFunc

NewAutowirePass returns a compiler pass that automatically wires the arguments of factories, method calls and functions based on their types.

func NewCycleValidationPass added in v0.3.0

func NewCycleValidationPass() CompilerPassFunc

NewCycleValidationPass returns a compiler pass that validates that there are no circular references.

func NewEagerInitPass added in v0.3.0

func NewEagerInitPass() CompilerPassFunc

NewEagerInitPass returns a compiler pass that initializes all services that are marked as eager.

func NewFinalizationPass added in v0.6.6

func NewFinalizationPass() CompilerPassFunc

func NewReferenceValidationPass added in v0.3.0

func NewReferenceValidationPass() CompilerPassFunc

NewReferenceValidationPass returns a compiler pass that validates all arguments of factories, method calls and functions that reference other services. It ensures that the referenced services exist.

func (CompilerPassFunc) Compile added in v0.3.0

func (fn CompilerPassFunc) Compile(builder *ContainerBuilder) error

type CompilerPassStage added in v0.3.0

type CompilerPassStage uint8
const (
	PreOptimisation CompilerPassStage = iota
	Optimisation
	PreValidation
	Validation
	PostValidation
	Finalization
	PostFinalization
)

type Container

type Container interface {
	Get(id ID) (any, error)
	GetByTag(tag TagID) ([]any, error)
	Has(id ID) bool
	CallFunction(id ID) error
	CallFunctions() error
	HasFunction(id ID) bool
	Initialised(id ID) bool
}

Container is a dependency injection container. It holds definitions of services and is responsible for building and storing instances of services.

type ContainerBuilder added in v0.3.0

type ContainerBuilder struct {
	// contains filtered or unexported fields
}

ContainerBuilder is a builder for Container. It provides a fluent interface to inspect and configure the container. Once Build() is called, this builder is locked and no longer usable. Subsequent calls to Build() will return an error and any other method may panic.

func NewContainerBuilder added in v0.3.0

func NewContainerBuilder() *ContainerBuilder

func (*ContainerBuilder) AddAliases added in v0.3.0

func (b *ContainerBuilder) AddAliases(aliases ...Alias) *ContainerBuilder

func (*ContainerBuilder) AddCompilerPass added in v0.4.0

func (b *ContainerBuilder) AddCompilerPass(stage CompilerPassStage, priority int, pass CompilerPass) *ContainerBuilder

func (*ContainerBuilder) AddDefinitions added in v0.3.0

func (b *ContainerBuilder) AddDefinitions(definitions ...*Definition) *ContainerBuilder

func (*ContainerBuilder) AddFunctions added in v0.7.0

func (b *ContainerBuilder) AddFunctions(functions ...*FunctionDefinition)

func (*ContainerBuilder) Build added in v0.3.0

func (b *ContainerBuilder) Build() (Container, error)

func (*ContainerBuilder) GetAlias added in v0.3.0

func (b *ContainerBuilder) GetAlias(id ID) (Alias, bool)

func (*ContainerBuilder) GetAliases added in v0.3.0

func (b *ContainerBuilder) GetAliases() []Alias

func (*ContainerBuilder) GetDefinition added in v0.3.0

func (b *ContainerBuilder) GetDefinition(id ID) (*Definition, bool)

func (*ContainerBuilder) GetDefinitions added in v0.3.0

func (b *ContainerBuilder) GetDefinitions() []*Definition

func (*ContainerBuilder) GetFunction added in v0.7.0

func (b *ContainerBuilder) GetFunction(id ID) (*FunctionDefinition, bool)

func (*ContainerBuilder) GetFunctions added in v0.7.0

func (b *ContainerBuilder) GetFunctions() []*FunctionDefinition

func (*ContainerBuilder) RemoveAliases added in v0.3.0

func (b *ContainerBuilder) RemoveAliases(ids ...ID) *ContainerBuilder

func (*ContainerBuilder) RemoveDefinitions added in v0.3.0

func (b *ContainerBuilder) RemoveDefinitions(ids ...ID) *ContainerBuilder

func (*ContainerBuilder) SetAliases added in v0.3.0

func (b *ContainerBuilder) SetAliases(aliases ...Alias) *ContainerBuilder

func (*ContainerBuilder) SetDefinitions added in v0.3.0

func (b *ContainerBuilder) SetDefinitions(definitions ...*Definition) *ContainerBuilder

func (*ContainerBuilder) SetFunctions added in v0.7.0

func (b *ContainerBuilder) SetFunctions(functions ...*FunctionDefinition)

type Definition added in v0.3.0

type Definition struct {
	// contains filtered or unexported fields
}

Definition describes a service. It stores all information needed to build an instance of a service, and it tells the container how to handle the service.

func NewDefinition added in v0.3.0

func NewDefinition(id ID, factory *Factory) *Definition

func (*Definition) AddMethodCalls added in v0.3.0

func (d *Definition) AddMethodCalls(methodCalls ...*Method) *Definition

func (*Definition) AddTags added in v0.3.0

func (d *Definition) AddTags(tags ...*Tag) *Definition

func (*Definition) GetFactory added in v0.3.0

func (d *Definition) GetFactory() *Factory

func (*Definition) GetMethodCalls added in v0.3.0

func (d *Definition) GetMethodCalls() []*Method

func (*Definition) GetTags added in v0.3.0

func (d *Definition) GetTags() []*Tag

func (*Definition) ID added in v0.3.0

func (d *Definition) ID() ID

func (*Definition) IsAutowired added in v0.4.0

func (d *Definition) IsAutowired() bool

func (*Definition) IsLazy added in v0.3.0

func (d *Definition) IsLazy() bool

func (*Definition) IsPublic added in v0.3.0

func (d *Definition) IsPublic() bool

func (*Definition) IsShared added in v0.4.0

func (d *Definition) IsShared() bool

func (*Definition) Of added in v0.3.0

func (d *Definition) Of() reflect.Type

func (*Definition) RemoveMethodCalls added in v0.3.0

func (d *Definition) RemoveMethodCalls(names ...string) *Definition

func (*Definition) RemoveTags added in v0.3.0

func (d *Definition) RemoveTags(ids ...TagID) *Definition

func (*Definition) SetAutowired added in v0.4.0

func (d *Definition) SetAutowired(autowired bool) *Definition

func (*Definition) SetFactory added in v0.3.0

func (d *Definition) SetFactory(factory *Factory) *Definition

func (*Definition) SetLazy added in v0.3.0

func (d *Definition) SetLazy(lazy bool) *Definition

func (*Definition) SetMethodCalls added in v0.3.0

func (d *Definition) SetMethodCalls(methodCalls ...*Method) *Definition

func (*Definition) SetPublic added in v0.3.0

func (d *Definition) SetPublic(public bool) *Definition

func (*Definition) SetShared added in v0.4.0

func (d *Definition) SetShared(shared bool) *Definition

func (*Definition) SetTags added in v0.3.0

func (d *Definition) SetTags(tags ...*Tag) *Definition

func (*Definition) String added in v0.3.0

func (d *Definition) String() string

type DefinitionBuilder added in v0.3.0

type DefinitionBuilder struct {
	// contains filtered or unexported fields
}

DefinitionBuilder is a helper for building Definition objects. It offers a fluent interface that does all the heavy lifting for the user. This is the recommended way of building a Definition.

func Svc

func Svc(factory any) *DefinitionBuilder

Svc returns a DefinitionBuilder for a service of type inferred from the passed factory.

func SvcT

func SvcT[T any](factory any) *DefinitionBuilder

SvcT returns a DefinitionBuilder for a service of type defined by the type parameter.

func (*DefinitionBuilder) Args added in v0.3.0

func (b *DefinitionBuilder) Args(args ...any) *DefinitionBuilder

func (*DefinitionBuilder) Autowired added in v0.3.0

func (b *DefinitionBuilder) Autowired() *DefinitionBuilder

func (*DefinitionBuilder) Build added in v0.3.0

func (b *DefinitionBuilder) Build() (*Definition, error)

func (*DefinitionBuilder) Eager added in v0.3.0

func (*DefinitionBuilder) ID added in v0.3.0

func (*DefinitionBuilder) Lazy added in v0.3.0

func (*DefinitionBuilder) MethodCall added in v0.3.0

func (b *DefinitionBuilder) MethodCall(name string, args ...any) *DefinitionBuilder

func (*DefinitionBuilder) NotAutowired added in v0.4.0

func (b *DefinitionBuilder) NotAutowired() *DefinitionBuilder

func (*DefinitionBuilder) NotShared added in v0.4.0

func (b *DefinitionBuilder) NotShared() *DefinitionBuilder

func (*DefinitionBuilder) Private added in v0.3.0

func (b *DefinitionBuilder) Private() *DefinitionBuilder

func (*DefinitionBuilder) Public added in v0.3.0

func (b *DefinitionBuilder) Public() *DefinitionBuilder

func (*DefinitionBuilder) Shared added in v0.4.0

func (b *DefinitionBuilder) Shared() *DefinitionBuilder

func (*DefinitionBuilder) Tags added in v0.3.0

func (b *DefinitionBuilder) Tags(tags ...any) *DefinitionBuilder

type Factory added in v0.3.0

type Factory struct {
	// contains filtered or unexported fields
}

Factory represents a function that creates a service.

func NewAutoFactory added in v0.3.0

func NewAutoFactory(fn any, args ...Argument) (*Factory, error)

NewAutoFactory returns a factory that creates a service of type inferred from the passed function signature.

func NewFactory added in v0.3.0

func NewFactory(of reflect.Type, fn reflect.Value, args ...Argument) (*Factory, error)

func NewFactoryT added in v0.3.0

func NewFactoryT[T any](fn any, args ...Argument) (*Factory, error)

NewFactoryT returns a factory that creates a service of type defined in the type parameter.

func (*Factory) GetArgs added in v0.3.0

func (fn *Factory) GetArgs() FuncArgumentsList

type FuncArgument added in v0.4.0

type FuncArgument struct {
	// contains filtered or unexported fields
}

func NewFuncArgument added in v0.4.0

func NewFuncArgument(typ reflect.Type, arg Argument) (*FuncArgument, error)

func (FuncArgument) Argument added in v0.4.0

func (a FuncArgument) Argument() Argument

func (FuncArgument) IsEmpty added in v0.4.0

func (a FuncArgument) IsEmpty() bool

func (FuncArgument) Type added in v0.4.0

func (a FuncArgument) Type() reflect.Type

type FuncArgumentsList added in v0.4.0

type FuncArgumentsList []*FuncArgument

func NewFuncArgumentsList added in v0.4.0

func NewFuncArgumentsList(fn reflect.Type, args ...Argument) (FuncArgumentsList, error)

func (FuncArgumentsList) Arguments added in v0.4.0

func (l FuncArgumentsList) Arguments() []Argument

func (FuncArgumentsList) ForEach added in v0.4.0

func (l FuncArgumentsList) ForEach(fn func(i uint, a *FuncArgument) error) error

func (FuncArgumentsList) Set added in v0.4.0

func (l FuncArgumentsList) Set(i uint, arg Argument) error

func (FuncArgumentsList) SetAuto added in v0.4.0

func (l FuncArgumentsList) SetAuto(args ...Argument) error

type Function added in v0.7.0

type Function struct {
	// contains filtered or unexported fields
}

func NewFunction added in v0.7.0

func NewFunction(fn any, args ...Argument) (*Function, error)

func (*Function) GetArgs added in v0.7.0

func (fn *Function) GetArgs() FuncArgumentsList

type FunctionDefinition added in v0.7.0

type FunctionDefinition struct {
	// contains filtered or unexported fields
}

func NewFunctionDefinition added in v0.7.0

func NewFunctionDefinition(id ID, fn *Function) *FunctionDefinition

func (*FunctionDefinition) GetFunction added in v0.7.0

func (d *FunctionDefinition) GetFunction() *Function

func (*FunctionDefinition) ID added in v0.7.0

func (d *FunctionDefinition) ID() ID

func (*FunctionDefinition) IsAutowired added in v0.7.0

func (d *FunctionDefinition) IsAutowired() bool

func (*FunctionDefinition) SetAutowired added in v0.7.0

func (d *FunctionDefinition) SetAutowired(autowired bool)

func (*FunctionDefinition) String added in v0.7.0

func (d *FunctionDefinition) String() string

type FunctionDefinitionBuilder added in v0.7.0

type FunctionDefinitionBuilder struct {
	// contains filtered or unexported fields
}

func Func added in v0.7.0

func Func(id ID, fn any, args ...any) *FunctionDefinitionBuilder

func (*FunctionDefinitionBuilder) Build added in v0.7.0

type ID added in v0.3.0

type ID string

func FQN

func FQN[T any]() ID

FQN returns the fully qualified name of the type parameter.

type InterfaceResolutionPass added in v0.3.0

type InterfaceResolutionPass struct{}

InterfaceResolutionPass resolves interfaces to their implementations. It inspects arguments of factories, method calls and functions of all definitions. If those arguments are interfaces, it tries to find a single implementation of that interface. If there is exactly one implementation, it creates an alias for that implementation, which allows the container to use it for instantiation.

func (InterfaceResolutionPass) Compile added in v0.3.0

func (p InterfaceResolutionPass) Compile(builder *ContainerBuilder) error

type Method added in v0.3.0

type Method struct {
	// contains filtered or unexported fields
}

Method represents a method of a service.

func NewMethod added in v0.3.0

func NewMethod(fn reflect.Method, args ...Argument) (*Method, error)

NewMethod returns a method of a service.

func (*Method) GetArgs added in v0.3.0

func (fn *Method) GetArgs() FuncArgumentsList

func (*Method) Name added in v0.3.0

func (fn *Method) Name() string

type OptionsFunc added in v0.3.0

type OptionsFunc func(opt *getOptions)

func WithID

func WithID(id ID) OptionsFunc

WithID returns an OptionsFunc that sets the ID of the service to get.

type Reference added in v0.3.0

type Reference struct {
	// contains filtered or unexported fields
}

Reference represents a dependency on another service. It is resolved by the container and must point at a valid service ID.

func NewReference added in v0.3.0

func NewReference(id ID, typ reflect.Type) *Reference

func (Reference) ID added in v0.3.0

func (r Reference) ID() ID

func (Reference) String added in v0.3.0

func (r Reference) String() string

func (Reference) Type added in v0.3.0

func (r Reference) Type() reflect.Type

type Tag added in v0.3.0

type Tag struct {
	// contains filtered or unexported fields
}

func NewTag added in v0.4.0

func NewTag(id TagID) *Tag

func (*Tag) AddParam added in v0.4.0

func (t *Tag) AddParam(name string, val any) *Tag

func (*Tag) GetParam added in v0.4.0

func (t *Tag) GetParam(name string) any

func (*Tag) HasParam added in v0.4.0

func (t *Tag) HasParam(name string) bool

func (*Tag) ID added in v0.4.0

func (t *Tag) ID() TagID

func (*Tag) Params added in v0.4.0

func (t *Tag) Params() map[string]any

func (*Tag) String added in v0.4.0

func (t *Tag) String() string

type TagID added in v0.4.0

type TagID string

type TaggedCollection added in v0.3.0

type TaggedCollection struct {
	// contains filtered or unexported fields
}

TaggedCollection represents a dependency on a collection of services tagged with a specific tag. It is resolved by the container and may be empty.

func NewTaggedCollection added in v0.3.0

func NewTaggedCollection(tag TagID, typ reflect.Type) *TaggedCollection

func (TaggedCollection) String added in v0.3.0

func (t TaggedCollection) String() string

func (TaggedCollection) Type added in v0.3.0

func (t TaggedCollection) Type() reflect.Type

type Value added in v0.3.0

type Value struct {
	// contains filtered or unexported fields
}

Value represents a literal dependency, known at compilation time and passed to the function as-is.

func NewValue added in v0.3.0

func NewValue(v any) *Value

func NewZero added in v0.3.2

func NewZero() *Value

func (Value) String added in v0.3.0

func (v Value) String() string

func (Value) Type added in v0.3.0

func (v Value) Type() reflect.Type

Directories

Path Synopsis
Package dig provides a default, package-level container and functions that interact with it.
Package dig provides a default, package-level container and functions that interact with it.
example
car

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL