Help us shape the future of Go! Take the 2026 Go Developer Survey

di

package
v2.10.2 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package di implements functions and data types supporting dependency injection patterns.

Overview

The dependency injection (DI) framework provides a type-safe way to manage dependencies between components in your application. It ensures that all dependencies are resolved correctly and that instances are created as singletons.

Core Concepts

Dependency - An abstract concept representing a service, function, or value with a specific type. Dependencies can be:

  • Simple values (API URLs, configuration strings, numbers)
  • Complex objects (HTTP clients, database connections)
  • Service interfaces
  • Functions

InjectionToken - A unique identifier for a dependency that includes type information. Created using MakeToken[T](name).

Provider - The implementation of a dependency. Providers specify:

  • Which dependency they provide (via an InjectionToken)
  • What other dependencies they need
  • How to create the instance

InjectableFactory - The container that manages all providers and resolves dependencies. All resolved instances are singletons.

Basic Usage

Creating and using dependencies:

import (
	"github.com/IBM/fp-go/v2/di"
	IOE "github.com/IBM/fp-go/v2/ioeither"
)

// Define injection tokens
var (
	ConfigToken = di.MakeToken[Config]("Config")
	DBToken     = di.MakeToken[Database]("Database")
	APIToken    = di.MakeToken[APIService]("APIService")
)

// Create providers
configProvider := di.ConstProvider(ConfigToken, Config{Port: 8080})

dbProvider := di.MakeProvider1(
	DBToken,
	ConfigToken.Identity(),
	func(cfg Config) IOResult[Database] {
		return ioresult.Of(NewDatabase(cfg))
	},
)

apiProvider := di.MakeProvider2(
	APIToken,
	ConfigToken.Identity(),
	DBToken.Identity(),
	func(cfg Config, db Database) IOResult[APIService] {
		return ioresult.Of(NewAPIService(cfg, db))
	},
)

// Create injector and resolve
injector := DIE.MakeInjector([]DIE.Provider{
	configProvider,
	dbProvider,
	apiProvider,
})

// Resolve the API service
resolver := di.Resolve(APIToken)
result := resolver(injector)()

Dependency Types

Identity (Required) - The dependency must be resolved, or the injection fails:

token.Identity() // Returns Dependency[T]

Option (Optional) - The dependency is optional, returns Option[T]:

token.Option() // Returns Dependency[Option[T]]

IOEither (Lazy Required) - Lazy evaluation, memoized singleton:

token.IOEither() // Returns Dependency[IOEither[error, T]]

IOOption (Lazy Optional) - Lazy optional evaluation:

token.IOOption() // Returns Dependency[IOOption[T]]

Provider Creation

Providers are created using MakeProvider functions with suffixes indicating the number of dependencies (0-15):

MakeProvider0 - No dependencies:

provider := di.MakeProvider0(
	token,
	ioresult.Of(value),
)

MakeProvider1 - One dependency:

provider := di.MakeProvider1(
	resultToken,
	dep1Token.Identity(),
	func(dep1 Dep1Type) IOResult[ResultType] {
		return ioresult.Of(createResult(dep1))
	},
)

MakeProvider2 - Two dependencies:

provider := di.MakeProvider2(
	resultToken,
	dep1Token.Identity(),
	dep2Token.Identity(),
	func(dep1 Dep1Type, dep2 Dep2Type) IOResult[ResultType] {
		return ioresult.Of(createResult(dep1, dep2))
	},
)

Constant Providers

For simple constant values:

provider := di.ConstProvider(token, value)

Default Implementations

Tokens can have default implementations that are used when no explicit provider is registered:

token := di.MakeTokenWithDefault0(
	"ServiceName",
	ioresult.Of(defaultImplementation),
)

// Or with dependencies
token := di.MakeTokenWithDefault2(
	"ServiceName",
	dep1Token.Identity(),
	dep2Token.Identity(),
	func(dep1 Dep1Type, dep2 Dep2Type) IOResult[ResultType] {
		return ioresult.Of(createDefault(dep1, dep2))
	},
)

Multi-Value Dependencies

For dependencies that can have multiple implementations:

// Create a multi-token
loggersToken := di.MakeMultiToken[Logger]("Loggers")

// Provide multiple items
consoleLogger := di.ConstProvider(loggersToken.Item(), ConsoleLogger{})
fileLogger := di.ConstProvider(loggersToken.Item(), FileLogger{})

// Resolve all items as an array
resolver := di.Resolve(loggersToken.Container())
loggers := resolver(injector)() // Returns []Logger

Lazy vs Eager Resolution

Eager (Identity/Option) - Resolved immediately when the injector is created:

dep1Token.Identity() // Resolved eagerly
dep2Token.Option()   // Resolved eagerly

Lazy (IOEither/IOOption) - Resolved only when accessed:

dep3Token.IOEither() // Resolved lazily
dep4Token.IOOption() // Resolved lazily

Lazy dependencies are memoized, so they're only created once.

Main Application Pattern

The framework provides a convenient pattern for running applications:

import (
	"github.com/IBM/fp-go/v2/di"
	IOE "github.com/IBM/fp-go/v2/ioeither"
)

// Define your main application logic
mainProvider := di.MakeProvider1(
	di.InjMain,
	APIToken.Identity(),
	func(api APIService) IOResult[any] {
		return ioresult.Of(api.Start())
	},
)

// Run the application
err := di.RunMain([]DIE.Provider{
	configProvider,
	dbProvider,
	apiProvider,
	mainProvider,
})()

Practical Examples

Example 1: Configuration-based Service

type Config struct {
	APIKey string
	Timeout int
}

type HTTPClient struct {
	config Config
}

var (
	ConfigToken = di.MakeToken[Config]("Config")
	ClientToken = di.MakeToken[HTTPClient]("HTTPClient")
)

configProvider := di.ConstProvider(ConfigToken, Config{
	APIKey: "secret",
	Timeout: 30,
})

clientProvider := di.MakeProvider1(
	ClientToken,
	ConfigToken.Identity(),
	func(cfg Config) IOResult[HTTPClient] {
		return ioresult.Of(HTTPClient{config: cfg})
	},
)

Example 2: Optional Dependencies

var (
	CacheToken  = di.MakeToken[Cache]("Cache")
	ServiceToken = di.MakeToken[Service]("Service")
)

// Service works with or without cache
serviceProvider := di.MakeProvider1(
	ServiceToken,
	CacheToken.Option(), // Optional dependency
	func(cache Option[Cache]) IOResult[Service] {
		return ioresult.Of(NewService(cache))
	},
)

Example 3: Lazy Dependencies

var (
	DBToken      = di.MakeToken[Database]("Database")
	ReporterToken = di.MakeToken[Reporter]("Reporter")
)

// Reporter only connects to DB when needed
reporterProvider := di.MakeProvider1(
	ReporterToken,
	DBToken.IOEither(), // Lazy dependency
	func(dbIO IOResult[Database]) IOResult[Reporter] {
		return ioresult.Of(NewReporter(dbIO))
	},
)

Function Reference

Token Creation:

  • MakeToken[T](name) InjectionToken[T] - Creates a unique injection token
  • MakeTokenWithDefault[T](name, factory) InjectionToken[T] - Token with default implementation
  • MakeTokenWithDefault0-15 - Token with default and N dependencies
  • MakeMultiToken[T](name) MultiInjectionToken[T] - Token for multiple implementations

Provider Creation:

  • ConstProvider[T](token, value) Provider - Simple constant provider
  • MakeProvider0[R](token, factory) Provider - Provider with no dependencies
  • MakeProvider1-15 - Providers with 1-15 dependencies
  • MakeProviderFactory0-15 - Lower-level factory creation

Resolution:

  • Resolve[T](token) ReaderIOEither[InjectableFactory, error, T] - Resolves a dependency

Application:

  • InjMain - Injection token for main application
  • Main - Resolver for main application
  • RunMain(providers) IO[error] - Runs the main application

Utility:

  • asDependency[T](t) Dependency - Converts to dependency interface
  • github.com/IBM/fp-go/v2/di/erasure - Type-erased DI implementation
  • github.com/IBM/fp-go/v2/ioeither - IO operations with error handling
  • github.com/IBM/fp-go/v2/option - Optional values
  • github.com/IBM/fp-go/v2/either - Either monad for error handling

[Provider]: github.com/IBM/fp-go/v2/di/erasure.Provider [InjectableFactory]: github.com/IBM/fp-go/v2/di/erasure.InjectableFactory [MakeInjector]: github.com/IBM/fp-go/v2/di/erasure.MakeInjector

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// InjMain is the [InjectionToken] for the main application
	InjMain = MakeToken[any]("APP")

	// Main is the resolver for the main application
	Main = Resolve(InjMain)
)

RunMain runs the main application from a set of [DIE.Provider]s

Functions

func ConstProvider

func ConstProvider[R any](token InjectionToken[R], value R) DIE.Provider

ConstProvider simple implementation for a provider with a constant value

func MakeProvider0

func MakeProvider0[R any](
	token InjectionToken[R],
	fct IOResult[R],
) DIE.Provider

func MakeProvider1

func MakeProvider1[T1 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	f func(T1) IOResult[R],
) DIE.Provider

MakeProvider1 creates a [DIE.Provider] for an InjectionToken from a function with 1 dependencies

func MakeProvider2

func MakeProvider2[T1, T2 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	f func(T1, T2) IOResult[R],
) DIE.Provider

MakeProvider2 creates a [DIE.Provider] for an InjectionToken from a function with 2 dependencies

func MakeProvider3

func MakeProvider3[T1, T2, T3 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	f func(T1, T2, T3) IOResult[R],
) DIE.Provider

MakeProvider3 creates a [DIE.Provider] for an InjectionToken from a function with 3 dependencies

func MakeProvider4

func MakeProvider4[T1, T2, T3, T4 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	f func(T1, T2, T3, T4) IOResult[R],
) DIE.Provider

MakeProvider4 creates a [DIE.Provider] for an InjectionToken from a function with 4 dependencies

func MakeProvider5

func MakeProvider5[T1, T2, T3, T4, T5 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	f func(T1, T2, T3, T4, T5) IOResult[R],
) DIE.Provider

MakeProvider5 creates a [DIE.Provider] for an InjectionToken from a function with 5 dependencies

func MakeProvider6

func MakeProvider6[T1, T2, T3, T4, T5, T6 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	f func(T1, T2, T3, T4, T5, T6) IOResult[R],
) DIE.Provider

MakeProvider6 creates a [DIE.Provider] for an InjectionToken from a function with 6 dependencies

func MakeProvider7

func MakeProvider7[T1, T2, T3, T4, T5, T6, T7 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	f func(T1, T2, T3, T4, T5, T6, T7) IOResult[R],
) DIE.Provider

MakeProvider7 creates a [DIE.Provider] for an InjectionToken from a function with 7 dependencies

func MakeProvider8

func MakeProvider8[T1, T2, T3, T4, T5, T6, T7, T8 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	f func(T1, T2, T3, T4, T5, T6, T7, T8) IOResult[R],
) DIE.Provider

MakeProvider8 creates a [DIE.Provider] for an InjectionToken from a function with 8 dependencies

func MakeProvider9

func MakeProvider9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9) IOResult[R],
) DIE.Provider

MakeProvider9 creates a [DIE.Provider] for an InjectionToken from a function with 9 dependencies

func MakeProvider10

func MakeProvider10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) IOResult[R],
) DIE.Provider

MakeProvider10 creates a [DIE.Provider] for an InjectionToken from a function with 10 dependencies

func MakeProvider11

func MakeProvider11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOResult[R],
) DIE.Provider

MakeProvider11 creates a [DIE.Provider] for an InjectionToken from a function with 11 dependencies

func MakeProvider12

func MakeProvider12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOResult[R],
) DIE.Provider

MakeProvider12 creates a [DIE.Provider] for an InjectionToken from a function with 12 dependencies

func MakeProvider13

func MakeProvider13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOResult[R],
) DIE.Provider

MakeProvider13 creates a [DIE.Provider] for an InjectionToken from a function with 13 dependencies

func MakeProvider14

func MakeProvider14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOResult[R],
) DIE.Provider

MakeProvider14 creates a [DIE.Provider] for an InjectionToken from a function with 14 dependencies

func MakeProvider15

func MakeProvider15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
	token InjectionToken[R],
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	d15 Dependency[T15],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOResult[R],
) DIE.Provider

MakeProvider15 creates a [DIE.Provider] for an InjectionToken from a function with 15 dependencies

func MakeProviderFactory0

func MakeProviderFactory0[R any](
	fct IOResult[R],
) DIE.ProviderFactory

func MakeProviderFactory1

func MakeProviderFactory1[T1 any, R any](
	d1 Dependency[T1],
	f func(T1) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory1 creates a [DIE.ProviderFactory] from a function with 1 arguments and 1 dependencies

func MakeProviderFactory2

func MakeProviderFactory2[T1, T2 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	f func(T1, T2) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory2 creates a [DIE.ProviderFactory] from a function with 2 arguments and 2 dependencies

func MakeProviderFactory3

func MakeProviderFactory3[T1, T2, T3 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	f func(T1, T2, T3) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory3 creates a [DIE.ProviderFactory] from a function with 3 arguments and 3 dependencies

func MakeProviderFactory4

func MakeProviderFactory4[T1, T2, T3, T4 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	f func(T1, T2, T3, T4) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory4 creates a [DIE.ProviderFactory] from a function with 4 arguments and 4 dependencies

func MakeProviderFactory5

func MakeProviderFactory5[T1, T2, T3, T4, T5 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	f func(T1, T2, T3, T4, T5) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory5 creates a [DIE.ProviderFactory] from a function with 5 arguments and 5 dependencies

func MakeProviderFactory6

func MakeProviderFactory6[T1, T2, T3, T4, T5, T6 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	f func(T1, T2, T3, T4, T5, T6) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory6 creates a [DIE.ProviderFactory] from a function with 6 arguments and 6 dependencies

func MakeProviderFactory7

func MakeProviderFactory7[T1, T2, T3, T4, T5, T6, T7 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	f func(T1, T2, T3, T4, T5, T6, T7) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory7 creates a [DIE.ProviderFactory] from a function with 7 arguments and 7 dependencies

func MakeProviderFactory8

func MakeProviderFactory8[T1, T2, T3, T4, T5, T6, T7, T8 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	f func(T1, T2, T3, T4, T5, T6, T7, T8) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory8 creates a [DIE.ProviderFactory] from a function with 8 arguments and 8 dependencies

func MakeProviderFactory9

func MakeProviderFactory9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory9 creates a [DIE.ProviderFactory] from a function with 9 arguments and 9 dependencies

func MakeProviderFactory10

func MakeProviderFactory10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory10 creates a [DIE.ProviderFactory] from a function with 10 arguments and 10 dependencies

func MakeProviderFactory11

func MakeProviderFactory11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory11 creates a [DIE.ProviderFactory] from a function with 11 arguments and 11 dependencies

func MakeProviderFactory12

func MakeProviderFactory12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory12 creates a [DIE.ProviderFactory] from a function with 12 arguments and 12 dependencies

func MakeProviderFactory13

func MakeProviderFactory13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory13 creates a [DIE.ProviderFactory] from a function with 13 arguments and 13 dependencies

func MakeProviderFactory14

func MakeProviderFactory14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory14 creates a [DIE.ProviderFactory] from a function with 14 arguments and 14 dependencies

func MakeProviderFactory15

func MakeProviderFactory15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	d15 Dependency[T15],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOResult[R],
) DIE.ProviderFactory

MakeProviderFactory15 creates a [DIE.ProviderFactory] from a function with 15 arguments and 15 dependencies

func Resolve

func Resolve[T any](token InjectionToken[T]) RIOR.ReaderIOResult[DIE.InjectableFactory, T]

Resolve performs a type safe resolution of a dependency

Example

ExampleResolve demonstrates the basic wiring: tokens identify the dependencies, providers implement them and the injector resolves them transitively

package main

import (
	"fmt"

	A "github.com/IBM/fp-go/v2/array"
	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/ioresult"

	S "github.com/IBM/fp-go/v2/string"
)

var renderString = E.Fold(error.Error, F.Identity[string])

func main() {
	// the tokens carry the type of the dependency
	injHost := di.MakeToken[string]("host")
	injPort := di.MakeToken[int]("port")
	injURL := di.MakeToken[string]("url")

	injector := DIE.MakeInjector(A.From(
		di.ConstProvider(injHost, "example.com"),
		di.ConstProvider(injPort, 8443),
		// the URL is assembled from the host and the port
		di.MakeProvider2(
			injURL,
			injHost.Identity(),
			injPort.Identity(),
			func(host string, port int) di.IOResult[string] {
				return ioresult.Of(fmt.Sprintf("https://%s:%d", host, port))
			},
		),
	))

	// resolving returns an effect, running it produces the value
	fmt.Println(renderString(di.Resolve(injURL)(injector)()))

}
Output:
https://example.com:8443
Example (MissingProvider)

ExampleResolve_missingProvider demonstrates that resolving a dependency without a provider fails instead of panicking

package main

import (
	"fmt"

	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"

	S "github.com/IBM/fp-go/v2/string"
)

var renderString = E.Fold(error.Error, F.Identity[string])

func main() {
	injDatabase := di.MakeToken[string]("database")

	fmt.Println(renderString(di.Resolve(injDatabase)(DIE.MakeInjector(DIE.Empty))()))

}
Output:
no provider for dependency [database]
Example (Singleton)

ExampleResolve_singleton demonstrates that every dependency is created at most once, no matter how many other dependencies refer to it

package main

import (
	"fmt"

	A "github.com/IBM/fp-go/v2/array"
	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/ioresult"
	"github.com/IBM/fp-go/v2/result"

	S "github.com/IBM/fp-go/v2/string"
)

var renderString = E.Fold(error.Error, F.Identity[string])

func main() {
	injCount := di.MakeToken[int]("counter")
	injLeft := di.MakeToken[string]("left")
	injRight := di.MakeToken[string]("right")
	injBoth := di.MakeToken[string]("both")

	var created int

	injector := DIE.MakeInjector(A.From(
		di.MakeProvider0(injCount, di.IOResult[int](func() di.Result[int] {
			created++
			return result.Of(created)
		})),
		di.MakeProvider1(injLeft, injCount.Identity(), func(c int) di.IOResult[string] {
			return ioresult.Of(fmt.Sprintf("left sees %d", c))
		}),
		di.MakeProvider1(injRight, injCount.Identity(), func(c int) di.IOResult[string] {
			return ioresult.Of(fmt.Sprintf("right sees %d", c))
		}),
		di.MakeProvider2(injBoth, injLeft.Identity(), injRight.Identity(),
			func(left, right string) di.IOResult[string] {
				return ioresult.Of(left + ", " + right)
			}),
	))

	fmt.Println(renderString(di.Resolve(injBoth)(injector)()))
	fmt.Println("created:", created)

}
Output:
left sees 1, right sees 1
created: 1

Types

type Dependency

type Dependency[T any] interface {
	DIE.Dependency
	// Unerase converts a value with erased type signature into a strongly typed value
	Unerase(val any) Result[T]
}

Dependency describes the relationship to a service, that has a type and a behaviour such as required, option or lazy

type Entry added in v2.0.1

type Entry[K comparable, V any] = record.Entry[K, V]

Entry represents a key-value pair in a record/map structure.

type IOOption

type IOOption[T any] = iooption.IOOption[T]

IOOption represents a synchronous computation that may not produce a value.

type IOResult

type IOResult[T any] = ioresult.IOResult[T]

IOResult represents a synchronous computation that may fail with an error.

type InjectionToken

type InjectionToken[T any] interface {
	Dependency[T]
	// Identity idenifies this dependency as a mandatory, required dependency, it will be resolved eagerly and injected as `T`.
	// If the dependency cannot be resolved, the resolution process fails
	Identity() Dependency[T]
	// Option identifies this dependency as optional, it will be resolved eagerly and injected as [Option[T]].
	// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as [O.None[T]]
	Option() Dependency[Option[T]]
	// IOEither identifies this dependency as mandatory but it will be resolved lazily as a [IOResult[T]]. This
	// value is memoized to make sure the dependency is a singleton.
	// If the dependency cannot be resolved, the resolution process fails
	IOEither() Dependency[IOResult[T]]
	// IOOption identifies this dependency as optional but it will be resolved lazily as a [IOOption[T]]. This
	// value is memoized to make sure the dependency is a singleton.
	// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as the none value.
	IOOption() Dependency[IOOption[T]]
}

InjectionToken uniquely identifies a dependency by giving it an Id, Type and name

func MakeToken

func MakeToken[T any](name string) InjectionToken[T]

MakeToken create a unique InjectionToken for a specific type

func MakeTokenWithDefault

func MakeTokenWithDefault[T any](name string, providerFactory DIE.ProviderFactory) InjectionToken[T]

MakeToken create a unique InjectionToken for a specific type

func MakeTokenWithDefault0

func MakeTokenWithDefault0[R any](name string, fct IOResult[R]) InjectionToken[R]

MakeTokenWithDefault0 creates a unique InjectionToken for a specific type with an attached default [DIE.Provider]

Example

ExampleMakeTokenWithDefault0 demonstrates a token that carries its own default implementation, which applies unless an explicit provider overrides it

package main

import (
	"fmt"

	A "github.com/IBM/fp-go/v2/array"
	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/ioresult"

	S "github.com/IBM/fp-go/v2/string"
)

var renderInt = E.Fold(error.Error, S.Format[int]("%d"))

func main() {
	injRetries := di.MakeTokenWithDefault0("retries", ioresult.Of(3))

	// no explicit provider, the default applies
	fmt.Println(renderInt(di.Resolve(injRetries)(DIE.MakeInjector(DIE.Empty))()))

	// an explicit provider wins over the default
	overridden := DIE.MakeInjector(A.From(di.ConstProvider(injRetries, 10)))
	fmt.Println(renderInt(di.Resolve(injRetries)(overridden)()))

}
Output:
3
10

func MakeTokenWithDefault1

func MakeTokenWithDefault1[T1 any, R any](
	name string,
	d1 Dependency[T1],
	f func(T1) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault1 creates an InjectionToken with a default implementation with 1 dependencies

func MakeTokenWithDefault2

func MakeTokenWithDefault2[T1, T2 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	f func(T1, T2) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault2 creates an InjectionToken with a default implementation with 2 dependencies

func MakeTokenWithDefault3

func MakeTokenWithDefault3[T1, T2, T3 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	f func(T1, T2, T3) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault3 creates an InjectionToken with a default implementation with 3 dependencies

func MakeTokenWithDefault4

func MakeTokenWithDefault4[T1, T2, T3, T4 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	f func(T1, T2, T3, T4) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault4 creates an InjectionToken with a default implementation with 4 dependencies

func MakeTokenWithDefault5

func MakeTokenWithDefault5[T1, T2, T3, T4, T5 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	f func(T1, T2, T3, T4, T5) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault5 creates an InjectionToken with a default implementation with 5 dependencies

func MakeTokenWithDefault6

func MakeTokenWithDefault6[T1, T2, T3, T4, T5, T6 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	f func(T1, T2, T3, T4, T5, T6) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault6 creates an InjectionToken with a default implementation with 6 dependencies

func MakeTokenWithDefault7

func MakeTokenWithDefault7[T1, T2, T3, T4, T5, T6, T7 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	f func(T1, T2, T3, T4, T5, T6, T7) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault7 creates an InjectionToken with a default implementation with 7 dependencies

func MakeTokenWithDefault8

func MakeTokenWithDefault8[T1, T2, T3, T4, T5, T6, T7, T8 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	f func(T1, T2, T3, T4, T5, T6, T7, T8) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault8 creates an InjectionToken with a default implementation with 8 dependencies

func MakeTokenWithDefault9

func MakeTokenWithDefault9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault9 creates an InjectionToken with a default implementation with 9 dependencies

func MakeTokenWithDefault10

func MakeTokenWithDefault10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault10 creates an InjectionToken with a default implementation with 10 dependencies

func MakeTokenWithDefault11

func MakeTokenWithDefault11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault11 creates an InjectionToken with a default implementation with 11 dependencies

func MakeTokenWithDefault12

func MakeTokenWithDefault12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault12 creates an InjectionToken with a default implementation with 12 dependencies

func MakeTokenWithDefault13

func MakeTokenWithDefault13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault13 creates an InjectionToken with a default implementation with 13 dependencies

func MakeTokenWithDefault14

func MakeTokenWithDefault14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault14 creates an InjectionToken with a default implementation with 14 dependencies

func MakeTokenWithDefault15

func MakeTokenWithDefault15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
	name string,
	d1 Dependency[T1],
	d2 Dependency[T2],
	d3 Dependency[T3],
	d4 Dependency[T4],
	d5 Dependency[T5],
	d6 Dependency[T6],
	d7 Dependency[T7],
	d8 Dependency[T8],
	d9 Dependency[T9],
	d10 Dependency[T10],
	d11 Dependency[T11],
	d12 Dependency[T12],
	d13 Dependency[T13],
	d14 Dependency[T14],
	d15 Dependency[T15],
	f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOResult[R],
) InjectionToken[R]

MakeTokenWithDefault15 creates an InjectionToken with a default implementation with 15 dependencies

type MultiInjectionToken

type MultiInjectionToken[T any] interface {
	// Container returns the injection token used to request an array of all provided items
	Container() InjectionToken[[]T]
	// Item returns the injection token used to provide an item
	Item() InjectionToken[T]
}

MultiInjectionToken uniquely identifies a dependency by giving it an Id, Type and name that can have multiple implementations. Implementations are provided via the MultiInjectionToken.Item injection token.

func MakeMultiToken

func MakeMultiToken[T any](name string) MultiInjectionToken[T]

MakeMultiToken creates a MultiInjectionToken

Example

ExampleMakeMultiToken demonstrates a dependency with multiple implementations. Each implementation provides the item token, consumers depend on the container token.

package main

import (
	"fmt"
	"strings"

	A "github.com/IBM/fp-go/v2/array"
	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/ioresult"

	S "github.com/IBM/fp-go/v2/string"
)

var renderString = E.Fold(error.Error, F.Identity[string])

func main() {
	middleware := di.MakeMultiToken[string]("middleware")
	injChain := di.MakeToken[string]("chain")

	injector := DIE.MakeInjector(A.From(
		di.ConstProvider(middleware.Item(), "logging"),
		di.ConstProvider(middleware.Item(), "tracing"),
		di.MakeProvider1(injChain, middleware.Container().Identity(),
			func(items []string) di.IOResult[string] {
				return ioresult.Of(strings.Join(items, " -> "))
			}),
	))

	fmt.Println(renderString(di.Resolve(injChain)(injector)()))

}
Output:
logging -> tracing
Example (Empty)

ExampleMakeMultiToken_empty demonstrates that a container token without any item provider resolves to the empty array rather than failing

package main

import (
	"fmt"

	A "github.com/IBM/fp-go/v2/array"
	"github.com/IBM/fp-go/v2/di"

	DIE "github.com/IBM/fp-go/v2/di/erasure"

	E "github.com/IBM/fp-go/v2/either"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/ioresult"

	S "github.com/IBM/fp-go/v2/string"
)

var renderString = E.Fold(error.Error, F.Identity[string])

func main() {
	middleware := di.MakeMultiToken[string]("middleware")
	injChain := di.MakeToken[string]("chain")

	injector := DIE.MakeInjector(A.From(
		di.MakeProvider1(injChain, middleware.Container().Identity(),
			func(items []string) di.IOResult[string] {
				return ioresult.Of(fmt.Sprintf("%d middlewares", len(items)))
			}),
	))

	fmt.Println(renderString(di.Resolve(injChain)(injector)()))

}
Output:
0 middlewares

type Option

type Option[T any] = option.Option[T]

Option represents an optional value that may or may not be present.

type Result

type Result[T any] = result.Result[T]

Result represents a computation that may fail with an error.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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