di

module
v2.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 16, 2023 License: MIT

README

di

di (dependency-injection) saves you from writing boiler-plate setup code in your main (and elsewhere) function by automating the creation of functions which build the providers you want injected.

Installation

go install gitlab.com/cosban/di/v2/cmd/di@latest

Usage

  1. Create a provider file.
  2. Add a go:generate comment to provider file like so
//go:generate di generate --source=filename.go --output=filename.gen.go

If the output flag is not specified, the generated code will be printed to stdout.

What is a provider file?

At its core, a provider is simply an exported function that delivers a specific output. This output may or may not serve as a dependency for other providers.

A provider file serves as a central repository for defining providers and their respective prerequisites. It essentially encapsulates functions that won't be explicitly invoked by your code.

Examples More detailed examples are located within the [examples/|examples/] directory

//go:generate di generate --source=example.go
package example

import "fmt"

func Path() string {
    return "localhost"
}

func Port() int {
    return 80
}

func Address(host string, port int) string {
    return fmt.Sprintf("%s:%d", host, port)
}

Using the go generate command on example.go would produce the following output

// Code generated by di; DO NOT EDIT.
//
//	Source: example.go
//	Command: di generate --source=example.go
//	Version: gitlab.com/cosban/di/v2/cmd/di (devel)
package example

var singleton *ExampleComponent

func GetExampleComponent() *ExampleComponent {
	if singleton == nil {
		singleton = &ExampleComponent{}
	}
	return singleton
}

type ExampleComponent struct {
}

func (c *ExampleComponent) Path() string {
	return Path()
}
func (c *ExampleComponent) Port() int {
	return Port()
}
func (c *ExampleComponent) Address() string {
	return Address(
		c.Path(),
		c.Port(),
	)
}

Which could then be used in your main.go to retrieve a correctly formatted address without having to write the boilerplate or determine the order of which providers to create first.

package main 

import "example"

func main() {
    component := example.GetExampleComponent()
    fmt.Printf(component.Address())
}

Troubleshooting Errors

Type Example Message Mitigation
Missing dependencies di error: missing dependency detected: Dependency provider(s) for Foo() Bar are missing with the following identifiers: Baz() Qux Create a provider function named Baz which returns a Qux or rename the dependency to match another provider of Qux
Circular dependency di error: circular dependency detected: Foo() Bar <-> Baz() Qux and Baz() Qux <-> Foo() Bar Modify the dependency structure between Foo and Baz to eliminate any cyclical dependencies.
Invalid source di error: unable to parse source Fix your code.

Features

Singleton Providers

Singleton providers are providers which are only created once and then cached for future use. They're singletons.

To create a singleton, insert a // @singleton comment above the provider function.

// @singleton
func Bar() string {
    return "bar"
}
Component Embedding

Components, the generated structures that utilize providers to acquire their dependencies, can be integrated within provider files. This integration enables the reuse and modification of providers not only for testing purposes but also to eliminate redundant boilerplate code and facilitate the management of complex configurations.

To embed a component, insert // @component comment above the provider function responsible for returning a pointer to the component.

// @component
func ExampleComponent() *example.Component {
	return example.GetExampleComponent()
}

Key points to note:

  • All providers from the embedded component will be available to the newly generated component.
  • Provider definitions within components that share identical identifiers (name and return type) with those defined in the provider file will be overridden by the latter.
  • Multiple components may be embedded within the same provider file but errors will occur if two embedded components share providers with identical identifiers if that provider is not overridden by the current provider file.
  • The component generation process supports nested components, allowing the usage of components which themselves have embedded other components without any additional configuration.

Directories

Path Synopsis
cmd
di
complex
Code generated by di; DO NOT EDIT.
Code generated by di; DO NOT EDIT.
embed
Code generated by di; DO NOT EDIT.
Code generated by di; DO NOT EDIT.
generics
Code generated by di; DO NOT EDIT.
Code generated by di; DO NOT EDIT.
simple
Code generated by di; DO NOT EDIT.
Code generated by di; DO NOT EDIT.
singletons
Code generated by di; DO NOT EDIT.
Code generated by di; DO NOT EDIT.
cmd
pkg
di

Jump to

Keyboard shortcuts

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