inject

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2024 License: MIT Imports: 7 Imported by: 1

README

inject

The inject package is inspired by codecangsta/inject and provides simplified public methods for dependency injection in Go.

Features

  • Provide: Used to provide dependencies through a function.
  • Invoke: Used to resolve dependencies and invoke a function with them.
  • Resolve: Used to resolve a dependency by its type.
  • Apply: Used to apply dependencies to a struct.
  • SetParent: Used to set the parent injector.
  • Thread safety ensured
  • Supports injection through the inject tag of struct fields

Usage

Here's an example of how to use the inject package:

package inject_test

import (
	"fmt"

	"github.com/theplant/inject"
)

// Define interfaces and implementations
type Printer interface {
	Print() string
}

type SimplePrinter struct{}

func (p *SimplePrinter) Print() string {
	return "Printing document"
}

// New type definition
type DocumentDescription string

type Document struct {
	Injector *inject.Injector `inject:""` // Injector will be provided by default, so you can also get it if needed

	ID          string              // Not injected
	Description DocumentDescription `inject:""`         // Exported non-optional field
	Printer     Printer             `inject:""`         // Exported non-optional field
	Size        int64               `inject:"optional"` // Exported optional field
	page        int                 `inject:""`         // Unexported non-optional field
	name        string              `inject:"optional"` // Unexported optional field
}

func ExampleInjector() {
	inj := inject.New()

	// Provide dependencies
	if err := inj.Provide(
		func() Printer {
			return &SimplePrinter{}
		},
		func() string {
			return "A simple string"
		},
		func() DocumentDescription {
			return "A document description"
		},
		func() int {
			return 42
		},
	); err != nil {
		panic(err)
	}

	{
		// Resolve dependencies
		var printer Printer
		if err := inj.Resolve(&printer); err != nil {
			panic(err)
		}
		fmt.Println("Resolved printer:", printer.Print())
	}

	printDoc := func(doc *Document) {
		fmt.Printf("Document id: %q\n", doc.ID)
		fmt.Printf("Document description: %q\n", doc.Description)
		fmt.Printf("Document printer: %q\n", doc.Printer.Print())
		fmt.Printf("Document size: %d\n", doc.Size)
		fmt.Printf("Document page: %d\n", doc.page)
		fmt.Printf("Document name: %q\n", doc.name)
	}

	fmt.Println("-------")

	{
		// Invoke a function
		results, err := inj.Invoke(func(printer Printer) *Document {
			return &Document{
				// This value will be retained as it is not tagged with `inject`, despite string being provided
				ID: "idInvoked",
				// This value will be overridden since it is tagged with `inject` and DocumentDescription is provided
				Description: "DescriptionInvoked",
				// This value will be overridden with the same value since it is tagged with `inject` and Printer is provided
				Printer: printer,
				// This value will be retained since it is tagged with `inject:"optional"` and int64 is not provided
				Size: 100,
			}
		})
		if err != nil {
			panic(err)
		}

		printDoc(results[0].(*Document))
	}

	fmt.Println("-------")

	{
		// Apply dependencies to a struct instance
		doc := &Document{}
		if err := inj.Apply(doc); err != nil {
			panic(err)
		}

		printDoc(doc)
	}

	fmt.Println("-------")

	{
		// Create a child injector and then apply dependencies to a struct instance
		child := inject.New()
		child.SetParent(inj)

		doc := &Document{}
		if err := child.Apply(doc); err != nil {
			panic(err)
		}

		printDoc(doc)
	}

	// Output:
	// Resolved printer: Printing document
	// -------
	// Document id: "idInvoked"
	// Document description: "A document description"
	// Document printer: "Printing document"
	// Document size: 100
	// Document page: 42
	// Document name: "A simple string"
	// -------
	// Document id: ""
	// Document description: "A document description"
	// Document printer: "Printing document"
	// Document size: 0
	// Document page: 42
	// Document name: "A simple string"
	// -------
	// Document id: ""
	// Document description: "A document description"
	// Document printer: "Printing document"
	// Document size: 0
	// Document page: 42
	// Document name: "A simple string"
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrTypeNotProvided     = errors.New("type not provided")
	ErrTypeAlreadyProvided = errors.New("type already provided")
	ErrParentAlreadySet    = errors.New("parent already set")
)

Functions

This section is empty.

Types

type Injector

type Injector struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"fmt"

	"github.com/theplant/inject"
)

// Define interfaces and implementations
type Printer interface {
	Print() string
}

type SimplePrinter struct{}

func (p *SimplePrinter) Print() string {
	return "Printing document"
}

// New type definition
type DocumentDescription string

type Document struct {
	Injector *inject.Injector `inject:""` // Injector will be provided by default, so you can also get it if needed

	ID          string              // Not injected
	Description DocumentDescription `inject:""`         // Exported non-optional field
	Printer     Printer             `inject:""`         // Exported non-optional field
	Size        int64               `inject:"optional"` // Exported optional field
	page        int                 `inject:""`         // Unexported non-optional field
	name        string              `inject:"optional"` // Unexported optional field
}

func main() {
	inj := inject.New()

	// Provide dependencies
	if err := inj.Provide(
		func() Printer {
			return &SimplePrinter{}
		},
		func() string {
			return "A simple string"
		},
		func() DocumentDescription {
			return "A document description"
		},
		func() int {
			return 42
		},
	); err != nil {
		panic(err)
	}

	{
		// Resolve dependencies
		var printer Printer
		if err := inj.Resolve(&printer); err != nil {
			panic(err)
		}
		fmt.Println("Resolved printer:", printer.Print())
	}

	printDoc := func(doc *Document) {
		fmt.Printf("Document id: %q\n", doc.ID)
		fmt.Printf("Document description: %q\n", doc.Description)
		fmt.Printf("Document printer: %q\n", doc.Printer.Print())
		fmt.Printf("Document size: %d\n", doc.Size)
		fmt.Printf("Document page: %d\n", doc.page)
		fmt.Printf("Document name: %q\n", doc.name)
	}

	fmt.Println("-------")

	{
		// Invoke a function
		results, err := inj.Invoke(func(printer Printer) *Document {
			return &Document{
				// This value will be retained as it is not tagged with `inject`, despite string being provided
				ID: "idInvoked",
				// This value will be overridden since it is tagged with `inject` and DocumentDescription is provided
				Description: "DescriptionInvoked",
				// This value will be overridden with the same value since it is tagged with `inject` and Printer is provided
				Printer: printer,
				// This value will be retained since it is tagged with `inject:"optional"` and int64 is not provided
				Size: 100,
			}
		})
		if err != nil {
			panic(err)
		}

		printDoc(results[0].(*Document))
	}

	fmt.Println("-------")

	{
		// Apply dependencies to a struct instance
		doc := &Document{}
		if err := inj.Apply(doc); err != nil {
			panic(err)
		}

		printDoc(doc)
	}

	fmt.Println("-------")

	{
		// Create a child injector and then apply dependencies to a struct instance
		child := inject.New()
		child.SetParent(inj)

		doc := &Document{}
		if err := child.Apply(doc); err != nil {
			panic(err)
		}

		printDoc(doc)
	}

}
Output:

Resolved printer: Printing document
-------
Document id: "idInvoked"
Document description: "A document description"
Document printer: "Printing document"
Document size: 100
Document page: 42
Document name: "A simple string"
-------
Document id: ""
Document description: "A document description"
Document printer: "Printing document"
Document size: 0
Document page: 42
Document name: "A simple string"
-------
Document id: ""
Document description: "A document description"
Document printer: "Printing document"
Document size: 0
Document page: 42
Document name: "A simple string"

func New

func New() *Injector

func (*Injector) Apply

func (inj *Injector) Apply(val any) error

func (*Injector) Invoke

func (inj *Injector) Invoke(f any) ([]any, error)

func (*Injector) Provide

func (inj *Injector) Provide(fs ...any) error

func (*Injector) Resolve

func (inj *Injector) Resolve(ref any) error

func (*Injector) SetParent

func (inj *Injector) SetParent(parent *Injector) error

Jump to

Keyboard shortcuts

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