🛠 A full-featured dependency injection container for go programming language.

Overview

DI

Documentation Release Build Status Go Report Card Code Coverage

Dependency injection for Go programming language.

Tutorial | Examples | Advanced features

Dependency injection is one form of the broader technique of inversion of control. It is used to increase modularity of the program and make it extensible.

This library helps you to organize responsibilities in your codebase and make it easy to combine low-level implementation into high-level behavior without boilerplate.

Features

  • Intuitive auto wiring
  • Interface implementations
  • Constructor injection
  • Optional injection
  • Field injection
  • Lazy-loading
  • Tagging
  • Grouping
  • Cleanup

Documentation

You can use standard pkg.go.dev and inline code comments. If you do not have experience with auto-wiring libraries as google/wire, uber-go/dig or another - start with tutorial.

Install

go get github.com/goava/di

What it looks like

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/goava/di"
)

func main() {
	di.SetTracer(&di.StdTracer{})
	// create container
	c, err := di.New(
		di.Provide(NewContext),  // provide application context
		di.Provide(NewServer),   // provide http server
		di.Provide(NewServeMux), // provide http serve mux
		// controllers as []Controller group
		di.Provide(NewOrderController, di.As(new(Controller))),
		di.Provide(NewUserController, di.As(new(Controller))),
	)
	// handle container errors
	if err != nil {
		log.Fatal(err)
	}
	// invoke function
	if err := c.Invoke(StartServer); err != nil {
		log.Fatal(err)
	}
}

Full code available here.

Questions

If you have any questions, feel free to create an issue.

Issues
  • How to build a service conditionally?

    How to build a service conditionally?

    Hello.

    I'm considering introducing DI into my project. Your DI implementation container looks good enough :) But I have a question: how to create services that are created through user's configuration? Here's an example:

    package main
    
    import (
    	"github.com/goava/di"
    	"github.com/spf13/viper"
    )
    
    type ServiceInterface interface {
    	Do()
    }
    
    type DependencyA interface {}
    type ServiceImplementationA struct {DependencyA}
    func (s *ServiceImplementationA) Do() {}
    
    type DependencyB interface {}
    type ServiceImplementationB struct {DependencyB}
    func (s *ServiceImplementationB) Do() {}
    
    func NewService(config *viper.Viper) ServiceInterface {
    	if viper.GetString("preferred_service") == "B" {
    		// Resolve as ServiceImplementationB
    	}
    
    	// Otherwise resolve as ServiceImplementationA
    }
    
    func main() {
    	container, _ := di.New(
    		di.Provide(viper.New),
    		di.Provide(NewService),
    	)
    	var service ServiceInterface
    	container.Resolve(&service)
    }
    

    Depending on the configuration, I want to create a service interface implementation. But each implementation has its own dependencies list (I have not provided them manually in the example). I need a way to somehow call container.Resolve(&concreteImplementation) from the NewService function.

    Is there any way to do this? Or maybe I just misunderstand how it should be done at all?

    opened by erickskrauch 15
  • Unable to make interfaces group by using the same funtion interface implenentations

    Unable to make interfaces group by using the same funtion interface implenentations

    The title :) https://play.golang.org/p/ZvWhZaxyzM6

    package main
    
    import (
    	"context"
    	"log"
    
    	"github.com/goava/di"
    )
    
    type Interface interface {
    	Do(ctx context.Context) error
    }
    
    type FuncInterface func(ctx context.Context) error
    func (c FuncInterface) Do(ctx context.Context) error {
    	return c(ctx)
    }
    
    func createFirst() FuncInterface {
    	return func(ctx context.Context) error {
    		return nil
    	}
    }
    
    func createSecond() FuncInterface {
    	return func(ctx context.Context) error {
    		return nil
    	}
    }
    
    func main() {
    	container, err := di.New(
    		di.Provide(createFirst, di.As(new(Interface))),
    		di.Provide(createSecond, di.As(new(Interface))),
    	)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	var interfaces []Interface
    	err = container.Resolve(&interfaces)
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    

    The error:

    main.FuncInterface already exists in dependency graph
    
    opened by erickskrauch 11
  • Add support for di. Inject in  Invoke()

    Add support for di. Inject in Invoke()

    Actually, the title. I've prepared an example that shows the problem: https://play.golang.org/p/vZ2JvfmvJBB

    package main
    
    import (
    	"log"
    
    	"github.com/goava/di"
    )
    
    type Dependency struct {}
    
    func NewDependency() *Dependency {
    	return &Dependency{}
    }
    
    type Params struct {
    	di.Inject
    
    	Dependency *Dependency `di:""`
    }
    
    func InvokeWithDependencyAsParam(params Params) {
    	// Some code
    }
    
    func main() {
    	_, err := di.New(
    		di.Provide(NewDependency),
    		di.Invoke(InvokeWithDependencyAsParam),
    	)
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    
    enhancement 
    opened by erickskrauch 11
  • Using `di.WithName()` breaks when having one entry without a `di.Name()`

    Using `di.WithName()` breaks when having one entry without a `di.Name()`

    When I provide the Container with multiple implementations of an Object and have one that doesnt have a Name the container doesnt know how to resolve it properly and returns an error when resolving a named entry

    bug 
    opened by fionera 7
  • Implement AddParent() method

    Implement AddParent() method

    opened by chirino 7
  • Allow decorating of services in the container

    Allow decorating of services in the container

    I started to try to implement this but I dont really understand how the internals are working right now. My Idea was to add another Option to di which is called Decorate.

    package main
    
    import (
    	"fmt"
    
    	"github.com/goava/di"
    )
    
    func main() {
    	container, err := di.New(
    		di.Provide(NewExample),
    	)
    	if err != nil {
    		panic(err)
    	}
    	
    	container.Invoke(func(e Example) {
    		fmt.Println(e) // Will print "Example"
    	})
    
           err = container.Decorate(DecorateExample)
           if err != nil {
    		panic(err)
    	}
    
    	container.Invoke(func(e Example) {
    		fmt.Println(e) // Will print "Example is now Decorated"
    	})
    }
    
    type Example string
    
    func NewExample() Example {
    	return "Example"
    }
    
    func DecorateExample(e Example) Example {
    	return e + " is now Decorated"
    }
    

    This can also be expaned to have options like priority to allow ordered decorations. Of course this only works when the decorated type isnt used before decoration. So you would have to call Decorate before Invoking anything.

    under discussion 
    opened by fionera 7
  • Add a Application Start and Stop System

    Add a Application Start and Stop System

    I am currently using uber-go/fx and I want to switch to DI, but sadly DI is missing a core feature to not run the invokes in compile state, instead having a Start() and Stop() function to kick off the Invokes and run until a control signal got sent, like CTRL+C.

    	container := di.New(
    // options
    	)
    
    	startCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
    	defer cancel()
    	if err := container.Start(startCtx); err != nil {
    		log.Fatal(err)
    	}
    
           <- container.Done()
    
    	stopCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
    	defer cancel()
    	if err := container.Stop(stopCtx); err != nil {
    		log.Fatal(err)
    	}
    

    or less verbose if someone doesnt need full controll over the start and stop system

    	container := di.New(
    // options
    	)
    
             container.Run()
    
    opened by fionera 7
  • concurrent map read and map write

    concurrent map read and map write

    When calling "Invoke" function in multiple goroutine, it can lead to concurrent read and map write in this part of the code :

    // check cycle verified
    if !c.verified[param.Key()] {
    	err := checkCycles(c, param)
    	if err != nil {
    		return err
    	}
    	c.verified[param.Key()] = true
    }
    
    opened by gfyrag 6
  • Implement injectable struct.

    Implement injectable struct.

    Closes #2. Implements #5. @zeromake try this branch. I rework a struct field injection mechanism. Tags support with embedded di.Injectable or di.Parameter(for backward compatibility).

    package main
    
    import (
    	"net/http"
    
    	"github.com/goava/di"
    )
    
    type Application struct {
    	di.Injectable
    	Server *http.Server   `di:""`
    	Mux    *http.ServeMux `di:""`
    }
    
    func New() *Application {
    	return &Application{}
    }
    
    func main() {
    	var app *Application
    	_, err := di.New(
    		di.Provide(func() *http.Server { return &http.Server{} }),
    		di.Provide(http.NewServeMux),
    		di.Provide(New),
    		di.Resolve(&app),
    	)
    	if err != nil {
    		panic(err)
    	}
    	if app.Server == nil {
    		panic("server not found")
    	}
    	if app.Mux == nil {
    		panic("mux not found")
    	}
    }
    
    opened by defval 5
  • fix: you could not use a struct to for both di and json marshalling.

    fix: you could not use a struct to for both di and json marshalling.

    You must at least add an empty di:"" tag to struct fields to also support json marshalling. Added test case to verify it works.

    opened by chirino 5
  • Possibility to disable singleton behavior.

    Possibility to disable singleton behavior.

    Does it possible to disable singleton behavior for some dependencies? Probably some ResolveOption or ProvideOption for that.

    For example I want use goava/di container for testing with mocks. I have two different setups:

    • di.New(...) with production implementation of interfaces which is used for release builds.
    • di.New(...) with mocks which replace external APIs implementations.

    Majority of mock libs assumes that each test recreate mock object but di container always returns same instance of mock object. I can call di.New for each test case but it is not looks good.

    enhancement 
    opened by ont 2
Releases(v1.11.1)
Owner
Goava
Goava
Simple Dependency Injection Container

?? gocontainer gocontainer - Dependency Injection Container ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free to send pull requests!

Rafał Lorenz 14 Dec 10, 2020
A reflection based dependency injection toolkit for Go.

⚒️ dig A reflection based dependency injection toolkit for Go. Good for: Powering an application framework, e.g. Fx. Resolving the object graph during

Uber Go 2.3k Jan 15, 2022
Go Dependency Injection Framework

Dingo Dependency injection for go Hello Dingo Dingo works very very similiar to Guice Basically one binds implementations/factories to interfaces, whi

Flamingo 120 Dec 30, 2021
A dependency injection based application framework for Go.

?? Fx An application framework for Go that: Makes dependency injection easy. Eliminates the need for global state and func init(). Installation We rec

Uber Go 2.4k Jan 15, 2022
Simple and yet powerful Dependency Injection for Go

goioc/di: Dependency Injection Why DI in Go? Why IoC at all? I've been using Dependency Injection in Java for nearly 10 years via Spring Framework. I'

Go IoC 140 Jan 15, 2022
Dependency Injection and Inversion of Control package

Linker Linker is Dependency Injection and Inversion of Control package. It supports the following features: Components registry Automatic dependency i

Logrange 32 May 6, 2021
Strict Runtime Dependency Injection for Golang

wire Wire is runtime depedency injection/wiring for golang. It's designed to be strict to avoid your go application running without proper dependency

Muhammad Surya 35 Dec 16, 2021
Compile-time dependency injection for Go

Dihedral Dihedral is a compile-time injection framework for Go. Getting started > go get -u github.com/dimes/dihedral Create a type you want injected

null 76 Sep 4, 2020
Compile-time Dependency Injection for Go

Wire: Automated Initialization in Go Wire is a code generation tool that automates connecting components using dependency injection. Dependencies betw

Google 7.3k Jan 23, 2022
Generated dependency injection containers in go (golang)

Generation of dependency injection containers for go programs (golang). Dingo is a code generator. It generates dependency injection containers based

null 68 Jan 20, 2022
A dependency injection library that is focused on clean API and flexibility

Dependency injection DI is a dependency injection library that is focused on clean API and flexibility. DI has two types of top-level abstractions: Co

Sergey Treinis 3 Dec 10, 2021
Golang PE injection on windows

GoPEInjection Golang PE injection on windows See: https://malwareunicorn.org/workshops/peinjection.html Based on Cryptowall's PE injection technique.

malwareunicorn 139 Dec 25, 2021
two scripts written in golang that will help you recognize dependency confusion.

two scripts written in golang that will help you recognize dependency confusion.

gv1_ 5 Oct 4, 2021
A lightweight yet powerful IoC container for Go projects

Container A lightweight yet powerful IoC container for Go projects. It provides a simple, fluent and easy-to-use interface to make dependency injectio

GoLobby 287 Jan 16, 2022
Serverless Container Workflows

direktiv event-based serverless container workflows Check out our online demo: wf.direktiv.io What is Direktiv? Direktiv is a specification for a serv

vorteil.io pty ltd 149 Jan 22, 2022
An additive dependency injection container for Golang.

Alice Alice is an additive dependency injection container for Golang. Philosophy Design philosophy behind Alice: The application components should not

Minjie Zha 43 Sep 15, 2021
Simple Dependency Injection Container

?? gocontainer gocontainer - Dependency Injection Container ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free to send pull requests!

Rafał Lorenz 14 Dec 10, 2020
[deprecated] A full-featured SPDY library for the Go language.

Deprecated With the release of Go1.6 and the addition of http2 to the standard library, this package is no longer under active development. It is high

Jamie Hall 120 Aug 4, 2021
How we can run unit tests in parallel mode with failpoint injection taking effect and without injection race

This is a simple demo to show how we can run unit tests in parallel mode with failpoint injection taking effect and without injection race. The basic

amyangfei 1 Oct 31, 2021
Full-featured BitTorrent client package and utilities

torrent This repository implements BitTorrent-related packages and command-line utilities in Go. The emphasis is on use as a library from other projec

Matt Joiner 4.2k Jan 21, 2022
Full-featured, plugin-driven, extensible HTTP client toolkit for Go

gentleman Full-featured, plugin-driven, middleware-oriented toolkit to easily create rich, versatile and composable HTTP clients in Go. gentleman embr

Tom 932 Jan 12, 2022
A full-featured license tool to check and fix license headers and resolve dependencies' licenses.

SkyWalking Eyes A full-featured license tool to check and fix license headers and resolve dependencies' licenses. Usage You can use License-Eye in Git

The Apache Software Foundation 78 Jan 17, 2022
Full-featured BitTorrent client package and utilities

torrent This repository implements BitTorrent-related packages and command-line utilities in Go. The emphasis is on use as a library from other projec

Matt Joiner 4.2k Jan 21, 2022
A full-featured regex engine in pure Go based on the .NET engine

regexp2 - full featured regular expressions for Go Regexp2 is a feature-rich RegExp engine for Go. It doesn't have constant time guarantees like the b

Doug Clark 476 Jan 19, 2022
Full-featured test framework for Go! Assertions, mocking, input testing, output capturing, and much more! 🍕

testza ?? Testza is like pizza for Go - you could life without it, but why should you? Get The Module | Documentation | Contributing | Code of Conduct

Marvin Wendt 312 Jan 17, 2022
hiboot is a high performance web and cli application framework with dependency injection support

Hiboot - web/cli application framework About Hiboot is a cloud native web and cli application framework written in Go. Hiboot is not trying to reinven

hidevops.io 162 Jan 21, 2022
A reflection based dependency injection toolkit for Go.

⚒️ dig A reflection based dependency injection toolkit for Go. Good for: Powering an application framework, e.g. Fx. Resolving the object graph during

Uber Go 2.3k Jan 15, 2022
Go Dependency Injection Framework

Dingo Dependency injection for go Hello Dingo Dingo works very very similiar to Guice Basically one binds implementations/factories to interfaces, whi

Flamingo 120 Dec 30, 2021
A dependency injection based application framework for Go.

?? Fx An application framework for Go that: Makes dependency injection easy. Eliminates the need for global state and func init(). Installation We rec

Uber Go 2.4k Jan 15, 2022