kinit

package module
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2021 License: MIT Imports: 3 Imported by: 1

README

KInit

Go Reference codecov Report Card Mentioned in Awesome Go

Usage examples

Installation

go get github.com/go-kata/kinit

Status

This is a beta version. API is not stabilized for now.

Versioning

Till the first major release minor version (v0.x.0) must be treated as a major version and patch version (v0.0.x) must be treated as a minor version.

For example, changing of version from v0.1.0 to v0.1.1 indicates compatible changes, but when version changes v0.1.1 to v0.2.0 this means that the last version breaks the API.

How to use

This library provides the global IoC container which does the automatic Dependency Injection:

kinit.Global()

If you need a local one (e.g. for tests), you can create it as following:

ctr := kinit.NewContainer()

A local container must be filled up with constructors and processors manually whereas the global one can be filled up when initializing packages.

Constructors

Constructors are entities that create objects (dependencies for injection in context of the DI). They have the following interface:

type Constructor interface {
	
	Type() reflect.Type
	
	Parameters() []reflect.Type
	
	Create(a ...reflect.Value) (reflect.Value, kdone.Destructor, error)
	
}

Here Type returns a type of object to create, Parameters returns types of other objects required to create this object and finally Create creates and returns a new object and its destructor (usekdone.Noop, not nil, if object has no destructor).

To register a constructor in the container use the Provide method.

The container allows to have only one constructor for each type. However, the reflect.Type is the interface, and you can implement it as you want, e.g. as following:

type NamedType stuct {
	reflect.Type
	Name string
}

Just keep in mind that the container uses a simple comparison of reflect.Type instances when looks up for necessary constructors (as well as processors and already created objects).

Processors

Processors are entities that process already created objects. The container applies processors immediately after the object creation and before an object will be injected as a dependency at the first time. Processors have the following interface:

type Processor interface {
	
	Type() reflect.Type
	
	Parameters() []reflect.Type

	Process(obj reflect.Value, a ...reflect.Value) error
	
}

Here Type returns a type of object to process, Parameters returns types of other objects required to process this object and finally Process processes an object.

To register a processor in the container use the Attach method.

The container allows to have an unlimited number of processors for each type but doesn't guarantee the order of their calling.

Functors

Functors represent functions to be run in the container and have the following interface:

type Functor interface {
	
	Parameters() []reflect.Type
	
	Call(a ...reflect.Value) ([]Functor, error)
	
}

Here Parameters returns types of objects required to call a function and Call calls a function and may return further functors.

To run functors in the container use the Run method.

At the start of run the container creates so-called arena that holds all created objects (only one object for each type). If some object required as a dependency is already on the arena it will be used, otherwise it will be firstly created and processed. All objects that are on the arena at the end of run will be automatically destroyed.

The container runs given functors sequentially. Their dependencies are resolved recursively using registered constructors and processors. If functor (let's call it branched) returns further functors, the container runs all of them before continue running functors following the branched one. This is called the Depth-First Run.

KInitX

Go Reference

This subpackage provides the expansion set includes default handy implementations of main library interfaces along with other handy tools. In most cases the KInitX is all you need to use the entire KInit functionality.

There are following implementations:

Constructor represents a constructor based on a function. It accepts func(...) T, func(...) (T, error) and func(...) (T, kdone.Destructor, error) signatures where T is an arbitrary Go type.

kinitx.MustProvide(func(config *Config) (*Object, kdone.Destructor, error) { ... })

Opener represents a constructor based on a function that creates an implementation of the io.Closer interface. It accepts func(...) C and func(...) (C, error) signatures where C is an arbitrary implementation of the io.Closer interface.

kinitx.MustProvide(func(logger *log.Logger) (*sql.DB, error) { ... })

Initializer represents a memberwise initializer of a struct. It accepts a template struct like a YourType{} and a template struct pointer like a (*YourType)(nil) or new(YourType).

kinitx.MustProvide((*Config)(nil))

Binder represents a pseudo-constructor that casts an object to an interface. It accepts an interface pointer like a (*YourInterface)(nil).

kinitx.MustBind((*StorageInterface)(nil), (*PostgresStrorage)(nil))

Processor represents a processor based on a function. It accepts func(T, ...) and func(T, ...) error signatures where T is an arbitrary Go type.

kinitx.MustAttach((*Object).SetOptionalProperty)

Functor represents a functor based on a function. It accepts func(...), func(...) error, func(...) (kinit.Functor, error) and func(...) ([]kinit.Functor, error) signatures.

kinitx.MustRun(func(app *Application) error { ... })

KInitQ

Go Reference

The DI mechanism provided by the main library is reflection-based and works in the runtime. However, this subpackage makes it possible to validate the dependency graph semi-statically thanks to build tags.

Just add two main functions as following:

main.go

// +build !inspect

package main

import "github.com/go-kata/kinit/kinitx"

func main() { kinitx.MustRun(EntryPoint) }

main_inspect.go

// +build inspect

package main

import "github.com/go-kata/kinit/kinitx"

func main() { kinitx.MustInspect(nil) }

Now to validate the dependency graph of your program just run:

go run -tags inspect

Example output:

2 errors occurred:
    #1 🠖 cyclic dependency: *config.Config 🠖 config.Loader 🠖 *config.FileLoader 🠖 *config.Config
    #2 🠖 unsatisfied dependency: *sql.DB 🠖 *log.Logger

For more details learn the documentation and explore examples.

Putting all together

In the github.com/go-kata/examples repository you can find examples of how may the code uses this library looks like.

References

KDone is the library that provides tools for destroying objects.

KError is the library that provides tools for handling errors.

Documentation

Overview

Package kinit provides tools for creating objects.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Arena

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

Arena represents an objects holder.

func NewArena

func NewArena(parents ...*Arena) *Arena

NewArena returns a new arena with given parent arenas.

func (*Arena) Finalize

func (a *Arena) Finalize() error

Finalize destroys objects registered on this arena.

func (*Arena) Finalized added in v0.4.0

func (a *Arena) Finalized() bool

Finalized returns boolean specifies were objects registered on this arena destroyed.

func (*Arena) Get

func (a *Arena) Get(t reflect.Type) (obj reflect.Value, ok bool)

Get returns an object of the given type if registered on this arena or on the one of non-finalized parent arenas which will be bypassed in the order that they were passed to the NewArena.

func (*Arena) MustFinalize

func (a *Arena) MustFinalize()

MustFinalize is a variant of the Finalize that panics on error.

func (*Arena) MustPut added in v0.5.0

func (a *Arena) MustPut(t reflect.Type, obj reflect.Value, dtor kdone.Destructor)

MustPut is a variant of the Put that panics on error.

func (*Arena) Put added in v0.5.0

func (a *Arena) Put(t reflect.Type, obj reflect.Value, dtor kdone.Destructor) error

Put registers the given object on this arena.

type Constructor

type Constructor interface {
	// Type returns a type of an object that is created by this constructor.
	Type() reflect.Type
	// Parameters returns types of objects this constructor depends on.
	Parameters() []reflect.Type
	// Create creates and returns a new object.
	Create(a ...reflect.Value) (reflect.Value, kdone.Destructor, error)
}

Constructor represents an object constructor.

The usual identifier for variables of this type is ctor.

type Container

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

Container represents a dependency injection container.

The usual identifier for variables of this type is ctr.

func Global added in v0.5.0

func Global() *Container

Global returns the global container.

func NewContainer

func NewContainer() *Container

NewContainer returns a new dependency injection container.

func (*Container) Attach added in v0.4.0

func (c *Container) Attach(proc Processor) error

Attach registers the given processor in this container.

Multiple processors may be registered for one type, but there are no guaranty of order of their call.

func (*Container) Explore added in v0.5.0

func (c *Container) Explore(f func(reflect.Type, Constructor, []Processor) (next bool))

Explore calls f for each type presented in this container.

Nil constructor indicates that there are no registered constructor for the type but registered processors are there.

The traversal will be broken if f will return false.

func (*Container) Lookup added in v0.5.0

func (c *Container) Lookup(t reflect.Type) (Constructor, []Processor)

Lookup returns constructor and processors that are registered for the given type in this container.

Nil constructor indicates that there are no registered constructor for the type.

func (*Container) MustAttach added in v0.4.0

func (c *Container) MustAttach(proc Processor)

MustAttach is a variant of the Attach that panics on error.

func (*Container) MustProvide

func (c *Container) MustProvide(ctor Constructor)

MustProvide is a variant of the Provide that panics on error.

func (*Container) MustRun added in v0.4.0

func (c *Container) MustRun(functors ...Functor)

MustRun is a variant of the Run that panics on error.

func (*Container) Provide

func (c *Container) Provide(ctor Constructor) error

Provide registers the given constructor in this container.

Only one constructor for a type may be registered.

func (*Container) Run added in v0.4.0

func (c *Container) Run(functors ...Functor) (err error)

Run runs given functors sequentially resolving their dependencies recursively using this container. If some functor returns further functors all of them will be run before the running of functors that follows it.

All objects created during run will be automatically destroyed when it ends.

type Functor added in v0.4.0

type Functor interface {
	// Parameters returns types of objects this functor depends on.
	Parameters() []reflect.Type
	// Call calls a function and may return further functors.
	Call(a ...reflect.Value) ([]Functor, error)
}

Functor represents a function.

The usual identifier for variables of this type is fun.

type Processor

type Processor interface {
	// Type returns a type of an object that is processed by this processor.
	Type() reflect.Type
	// Parameters returns types of objects this processor depends on.
	Parameters() []reflect.Type
	// Process processes the given object.
	Process(obj reflect.Value, a ...reflect.Value) error
}

Processor represents an object processor.

The usual identifier for variables of this type is proc.

type Runtime added in v0.4.0

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

Runtime represents a runtime.

func MustNewRuntime added in v0.4.0

func MustNewRuntime(ctr *Container, arena *Arena) *Runtime

MustNewRuntime is a variant of the NewRuntime that panics on error.

func NewRuntime added in v0.4.0

func NewRuntime(ctr *Container, arena *Arena) (*Runtime, error)

NewRuntime returns a new runtime associated with given container and arena.

func (*Runtime) MustPut added in v0.5.0

func (r *Runtime) MustPut(t reflect.Type, obj reflect.Value, dtor kdone.Destructor)

MustPut is a variant of the Put that panics on error.

func (*Runtime) MustRun added in v0.4.0

func (r *Runtime) MustRun(functors ...Functor)

MustRun is a variant of Run that panics on error.

func (*Runtime) Put added in v0.5.0

func (r *Runtime) Put(t reflect.Type, obj reflect.Value, dtor kdone.Destructor) error

Put registers the given object on the associated arena.

func (*Runtime) Run added in v0.4.0

func (r *Runtime) Run(functors ...Functor) (err error)

Run runs given functors using the associated container. The created separate arena will use the associated arena as a parent.

Directories

Path Synopsis
Package kinitq provides the KInit quality inspection kit.
Package kinitq provides the KInit quality inspection kit.
Package kinitx provides the KInit expansion set.
Package kinitx provides the KInit expansion set.

Jump to

Keyboard shortcuts

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