inject

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2024 License: MIT Imports: 5 Imported by: 1

README

inject

inject is a small dependency injection library for Go.

GoDoc

go get -u github.com/infogulch/inject

Why?

Dependency Injection?

Dependency Injection (DI) is a software design pattern that promotes loose coupling between components by separating the creation and management of object dependencies from the objects themselves. The promise of this pattern is that it helps authors write more modular and testable code.

DI in Go?

In the wider programming world, dependency injection typically revolves around language level constructs like constructors. Go does not have constructors in that sense, only conventions like the common New() function. Consequently, usage of inject revolves around providing and requesting functions and types.

How to use

  1. Define your dependencies as structs, interfaces, functions that accept and return structs or interfaces, or slices of the previous.
  2. Call inject.New(), providing all of your dependencies and constructor funcs as arguments, to get a var scope *Scope which implements Injector.
  3. Request types with an Injector: (Note that Go does not support generic methods, so these must be regular functions.) a. Call the generic inject.Get like so: t, err := inject.Get[T](scope) to recursively evaluate the constructors to return a t, or an error if there was an issue. b. Call inject.Inject[T](scope, myfunc) to call the func with arguments sourced from the scope and return the func's return value. The func must return one value, and optionally an error.

How it works

Build an injection scope by calling inject.New with values, functions, and slices. Then call inject.Get and inject.Inject to get values and call functions with the types available in the scope.

Provide an object T and it will be returned when requested. Provide any function that returns a U (or a (U, error)), then that function will be called to produce a U when requested. If a function requires inputs its arguments will be extracted from the injection scope then called, recursively, until the originally requested type is returned.

Each type can only have one provider, that is, you can't have two functions that both return T, or provide a T directly and a func() T, etc. The exception to this is slices, which are concatenated together if more than one are provided. Like all types, only one of any specific primitive type is allowed. To get around this, name your type like type MyInt int.

The exception to the "one type one provider" rule is slices. Adding multiple slices of the same type (or slices of functions that return the same type) results the scope containing one slice that is the concatenation of the provided slices.

Example

See the example for a working example http server application that demonstrates middleware, repository, and handler patterns.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Get added in v0.2.0

func Get[T any](inj Injector) (t T, err error)

func Inject added in v0.2.0

func Inject[T any](j Injector, fn interface{}) (t T, err error)

Types

type Injectable added in v0.2.0

type Injectable interface {
	Type() reflect.Type
	Inject(Injector) (reflect.Value, error)
}

func As added in v0.2.0

func As[T any](v T) Injectable

type Injector

type Injector interface {
	Get(reflect.Type) (reflect.Value, error)
}

type Scope added in v0.2.0

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

func New

func New(args ...any) (*Scope, error)

func (*Scope) Get added in v0.2.0

func (h *Scope) Get(t reflect.Type) (reflect.Value, error)

func (*Scope) PutPool added in v0.2.0

func (h *Scope) PutPool()

func (*Scope) Scope added in v0.2.0

func (ph *Scope) Scope(args ...any) (*Scope, error)

Directories

Path Synopsis
example module

Jump to

Keyboard shortcuts

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