fig

package module
v0.0.0-...-2c9df49 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2017 License: MIT Imports: 6 Imported by: 0

README

Build Status

Fig

Fig is a dependency injection tool written in Go for Go. It was developed to help solve problem with initialization of structures with dependencies with dependencies with depend...

It is simple to use, lightweight and written in pure Go.

Common scenario when to use it is next. Lets assume you have a struct with fields of interface types and you want them to be initialized with right implementation depending if it is a prod, dev or test run. All you need to do is create Fig object and register to it all dependencies you would like to use. It is not necessary to initialize dependencies of dependencies because it will be done automatically. All registered objects will be treated as potential candidates for injection. After that just call Initialize method with struct you want to be initialized (it also can be reference to anonymous struct). Please be sure that you have registered reference to object if it's methods expect reference receiver.

Example

Lets assume we have next main.go file with some structs and we want to avoid manual assignments of all dependencies, so you can simply inject them.

package main

import (
    "fmt"
    "github.com/pavelmemory/fig"
)

type UserRepo interface {
    Find() []string
}

type MemUserRepo struct {
    message string
}

func (mur *MemUserRepo) Find() []string {
    return []string{"mem", mur.message}
}

type FileUserRepo struct {
    message string
}

func (fur *FileUserRepo) Find() []string {
    return []string{"file", fur.message}
}

type OrderRepo struct {
}

func (or *OrderRepo) Create() string {
    return "order created"
}

type Module struct {
    Name      string `fig:"env[ENV_NAME]"`
    OrderRepo *OrderRepo
    UserRepo
}

func main() {
    injector := fig.New(false)
    err := injector.Register(
        &MemUserRepo{message: "mes_1"},
    )
    if err != nil {
        panic(fmt.Sprintf("%#v", err))
    }
    
    module := new(Module)
    
    err = injector.Initialize(module)
    if err != nil {
        panic(fmt.Sprintf("%#v", err))
    }
        
    fmt.Println(module.Name)
    fmt.Println(module.Find())
    fmt.Println(module.OrderRepo.Create())
}

The result of execution ENV_NAME=DEV go run main.go is:

DEV
[mem mes_1]
order created

There are two modes how Fig works. In case you create Fig object with false constructor value will mean you want all fields of initialization structs to be injected. If you specify true then only fields with fig tag will be injected (it can be just empty tag like fig:"").

Example 'fig' injector with 'false' https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_2_test.go Example 'fig' injector with 'true' https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_3_test.go


Multiple implementations of interface

In case you have registered multiple implementations of one interface you need to define a policy that will help to find which implementation to inject. There are couple of configuration tags designed to help with it. You need to configure fields with tag fig and policies from list below This tag can have next configurations:

  • skip - expected value [true|false]. This field will be skipped at time of injection if provided value is true and the field has value it had before invocation of Initialize method (can be used with other configurations)
  • impl - expected value is a full name of type with package name github.com/proj/implement/SomeStructName It will be used in case you have registered multiple implementations of one interface. So object with provided name will be injected
  • qual - expected value is any string. It will be used in case you have registered multiple implementations of one interface. Implementation will be chosen based on value provided in this config and value that will be returned by Qualify() string method of one of registered implementations. If no one of candidates implements Qualifier interface or no equal to specified string returned it will lead to an error

Example https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_2_test.go


Any value by key

You can use reg configuration of fig tag to inject anything you want. You should register all values you want to use with RegisterValue(key string, value interface{}) error or RegisterValues(keyValues map[string]interface{}) error methods. For configuration fig:"reg[key1]" value associated with key key1 will be injected to the field.

  • reg - expected value is any string. Must be registered with RegisterValue or RegisterValues methods

Example https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_5_test.go


Environment variables injection

Scenario when you need some environment variable value is quite popular, so there is solution for that. Tag configuration env solves the problem of manual initialization of such values.

  • env - expected value is any string that can represent key of environment variable. Value of this environment variable will be assigned to field. There is no way to provide default value, so in such case it is better to use reg configuration

Example https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_1_test.go


Initialization of maps, slices and channels

Maps, slices and channels can be initialized as well.
For maps just new map struct will be created and injected.
For channels it is possible to define size of buffer. Default value is 1.
And for slices you can define length and capacity. Default length and capacity are 1.

  • size - expected value is integer. Used to specify size of channel or length of slice.
  • cap - expected value is integer. Used to specify capacity of slice. Can't be less than size for slices.

Example https://github.com/pavelmemory/fig/blob/master/examples/sample/sample_5_test.go

Documentation

Index

Constants

View Source
const (
	// fig tag itself
	FIG_TAG = "fig"
	// configurations for fig tag
	IMPL_TAG_KEY     = "impl"
	ENV_TAG_KEY      = "env"
	SKIP_TAG_KEY     = "skip"
	REG_TAG_KEY      = "reg"
	QUAL_TAG_KEY     = "qual"
	SIZE_TAG_KEY     = "size"
	CAPACITY_TAG_KEY = "cap"
)

Variables

View Source
var (
	ErrorCannotBeRegistered         = errors.New("provided value can't be registered")
	ErrorCannotBeHolder             = errors.New("provided value can't be holder")
	ErrorCannotDecideImplementation = errors.New("not able to get value to inject")
	ErrorRegisteredValueOverridden  = errors.New("already registered value was overridden")
	ErrorIncorrectTagConfiguration  = errors.New("invalid `fig` tag configuration")
)

Functions

This section is empty.

Types

type Fig

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

func New

func New(injectOnlyIfFigTagProvided bool) *Fig

func (*Fig) AssembleRegistered

func (fig *Fig) AssembleRegistered(assemblingChain *[]string) error

func (*Fig) Initialize

func (fig *Fig) Initialize(holder interface{}) error

func (*Fig) Register

func (fig *Fig) Register(impls ...interface{}) error

func (*Fig) RegisterValue

func (fig *Fig) RegisterValue(key string, value interface{}) error

func (*Fig) RegisterValues

func (fig *Fig) RegisterValues(keyValues map[string]interface{}) error

type FigError

type FigError struct {
	Error_ error
	Cause  string
}

func (FigError) Error

func (fe FigError) Error() string

type InjectStep

type InjectStep interface {
	Do() error
	Break() bool
}

type InjectStepFigTagRequiredCheck

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

func NewFigTagRequiredCheck

func NewFigTagRequiredCheck(fig *Fig, tag reflect.StructTag) *InjectStepFigTagRequiredCheck

func (*InjectStepFigTagRequiredCheck) Break

func (figTagRequired *InjectStepFigTagRequiredCheck) Break() bool

func (*InjectStepFigTagRequiredCheck) Do

func (figTagRequired *InjectStepFigTagRequiredCheck) Do() error

type InjectStepRegisteredValueSetup

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

func NewRegisteredValueSetup

func NewRegisteredValueSetup(fig *Fig, tag reflect.StructTag, holderElementField reflect.Value) *InjectStepRegisteredValueSetup

func (*InjectStepRegisteredValueSetup) Break

func (registeredValue *InjectStepRegisteredValueSetup) Break() bool

func (*InjectStepRegisteredValueSetup) Do

func (registeredValue *InjectStepRegisteredValueSetup) Do() error

type InjectStepSkipCheck

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

func NewSkipCheck

func NewSkipCheck(tag reflect.StructTag) *InjectStepSkipCheck

func (*InjectStepSkipCheck) Break

func (skipVerify *InjectStepSkipCheck) Break() bool

func (*InjectStepSkipCheck) Do

func (skipVerify *InjectStepSkipCheck) Do() error

type InjectStepValueSetup

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

func NewValueSetup

func NewValueSetup(fig *Fig,
	tag reflect.StructTag,
	holderElementField reflect.Value,
	recursive bool,
	assemblingChain *[]string) *InjectStepValueSetup

func (*InjectStepValueSetup) Break

func (valueSetup *InjectStepValueSetup) Break() bool

func (*InjectStepValueSetup) Do

func (valueSetup *InjectStepValueSetup) Do() error

type Qualifier

type Qualifier interface {
	Qualify() string
}

type StepMachine

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

func NewStepMachine

func NewStepMachine() *StepMachine

func (*StepMachine) Add

func (sm *StepMachine) Add(steps ...InjectStep) *StepMachine

func (*StepMachine) Do

func (sm *StepMachine) Do() error

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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