Simple and yet powerful Dependency Injection for Go

goioc/di: Dependency Injection

goioc

Go go.dev reference CodeFactor Go Report Card codecov Quality Gate Status DeepSource

Why DI in Go? Why IoC at all?

I've been using Dependency Injection in Java for nearly 10 years via Spring Framework. I'm not saying that one can't live without it, but it's proven to be very useful for large enterprise-level applications. You may argue that Go follows a completely different ideology, values different principles and paradigms than Java, and DI is not needed in this better world. And I can even partly agree with that. And yet I decided to create this light-weight Spring-like library for Go. You are free to not use it, after all 🙂

Is it the only DI library for Go?

No, of course not. There's a bunch of libraries around which serve a similar purpose (I even took inspiration from some of them). The problem is that I was missing something in all of these libraries... Therefore I decided to create Yet Another IoC Container that would rule them all. You are more than welcome to use any other library, for example this nice project. And still, I'd recommend stopping by here 😉

So, how does it work?

It's better to show than to describe. Take a look at this toy-example (error-handling is omitted to minimize code snippets):

services/weather_service.go

package services

import (
	"io/ioutil"
	"net/http"
)

type WeatherService struct {
}

func (ws *WeatherService) Weather(city string) (*string, error) {
	response, err := http.Get("https://wttr.in/" + city)
	if err != nil {
		return nil, err
	}
	all, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	weather := string(all)
	return &weather, nil
}

controllers/weather_controller.go

package controllers

import (
	"di-demo/services"
	"github.com/goioc/di"
	"net/http"
)

type WeatherController struct {
	// note that injection works even with unexported fields
	weatherService *services.WeatherService `di.inject:"weatherService"`
}

func (wc *WeatherController) Weather(w http.ResponseWriter, r *http.Request) {
	weather, _ := wc.weatherService.Weather(r.URL.Query().Get("city"))
	_, _ = w.Write([]byte(*weather))
}

init.go

package main

import (
	"di-demo/controllers"
	"di-demo/services"
	"github.com/goioc/di"
	"reflect"
)

func init() {
	_, _ = di.RegisterBean("weatherService", reflect.TypeOf((*services.WeatherService)(nil)))
	_, _ = di.RegisterBean("weatherController", reflect.TypeOf((*controllers.WeatherController)(nil)))
	_ = di.InitializeContainer()
}

main.go

package main

import (
	"di-demo/controllers"
	"github.com/goioc/di"
	"net/http"
)

func main() {
	http.HandleFunc("/weather", func(w http.ResponseWriter, r *http.Request) {
		di.GetInstance("weatherController").(*controllers.WeatherController).Weather(w, r)
	})
	_ = http.ListenAndServe(":8080", nil)
}

If you run it, you should be able to observe a neat weather forecast at http://localhost:8080/weather?city=London (or for any other city).

Of course, for such a simple example it may look like an overkill. But for larger projects with many interconnected services with complicated business logic, it can really simplify your life!

Looks nice... Give me some details!

The main component of the library is the Inversion of Control Container that contains and manages instances of your structures (called "beans").

Types of beans

  • Singleton. Exists only in one copy in the container. Every time you retrieve the instance from the container (or every time it's being injected to another bean) - it will be the same instance.
  • Prototype. It can exist in multiple copies: a new copy is created upon retrieval from the container (or upon injection into another bean).
  • Request. Similar to Prototype, however it has a few differences and features (since its lifecycle is bound to a web request):
    • Can't be injected to other beans.
    • Can't be manually retrieved from the Container.
    • Request beans are automatically injected to the context.Context of a corresponding http.Request.
    • If a Request bean implements io.Closer, it will be "closed" upon corresponding request's cancellation.

Beans registration

For the container to become aware of the beans, one must register them manually (unlike Java, unfortunately, we can't scan classpath to do it automatically, because Go runtime doesn't contain high-level information about types). How can one register beans in the container?

  • By type. This is described in the example above. A structure is declared with a field tagged with di.scope:"<scope>". This field can be even omitted - in this case, the default scope will be Singleton. Than the registration is done like this:
di.RegisterBean("beanID", reflect.TypeOf((*YourAwesomeStructure)(nil)))
  • Using pre-created instance. What if you already have an instance that you want to register as a bean? You can do it like this:
di.RegisterBeanInstance("beanID", yourAwesomeInstance)

For this type of beans, the only supported scope is Singleton, because I don't dare to clone your instances to enable prototyping 😅

  • Via bean factory. If you have a method that is producing instances for you, you can register it as a bean factory:
di.RegisterBeanFactory("beanID", Singleton, func() (interface{}, error) {
		return "My awesome string that is going to become a bean!", nil
	})

Feel free to use any scope with this method. By the way, you can even lookup other beans within the factory:

di.RegisterBeanFactory("beanID", Singleton, func() (interface{}, error) {
		return di.GetInstance("someOtherBeanID"), nil
	})

Beans initialization

There's a special interface InitializingBean that can be implemented to provide your bean with some initialization logic that will we executed after the container is initialized (for Singleton beans) or after the Prototype/Request instance is created. Again, you can also lookup other beans during initialization (since the container is ready by that time):

type PostConstructBean1 struct {
	Value string
}

func (pcb *PostConstructBean1) PostConstruct() error {
	pcb.Value = "some content"
	return nil
}

type PostConstructBean2 struct {
	Scope              Scope `di.scope:"prototype"`
	PostConstructBean1 *PostConstructBean1
}

func (pcb *PostConstructBean2) PostConstruct() error {
	instance, err := di.GetInstanceSafe("postConstructBean1")
	if err != nil {
		return err
	}
	pcb.PostConstructBean1 = instance.(*PostConstructBean1)
	return nil
}

Beans injection

As was mentioned above, one bean can be injected into another with the PostConstruct method. But the more handy way of doing it is by using a special tag:

type SingletonBean struct {
	SomeOtherBean *SomeOtherBean `di.inject:"someOtherBean"`
}

... or via interface ...

type SingletonBean struct {
	SomeOtherBean SomeOtherBeansInterface `di.inject:"someOtherBean"`
}

Note that you can refer depepndencies either by pointer, or by interface, but not by value. And just a reminder: you can't inject Request beans.

Sometimes we might want to have optional dependencies. By default, all declared depepndencies are considered to be requred: if some dependency is not found in the Container, you will get an error. But you can specify an optional dependency like this:

type SingletonBean struct {
	SomeOtherBean *string `di.inject:"someOtherBean" di.optional:"true"`
}

In this case, if someOtherBean is not found in the Container, you will get nill injected into this field.

Circular dependencies

The problem with all IoC containers is that beans' interconnection may suffer from so-called circular dependencies. Consider this example:

type CircularBean struct {
	Scope        Scope         `di.scope:"prototype"`
	CircularBean *CircularBean `di.inject:"circularBean"`
}

Trying to use such bean will result in the circular dependency detected for bean: circularBean error. There's no problem as such with referencing a bean from itself - if it's a Singleton bean. But doing it with Prototype/Request beans will lead to infinite creation of the instances. So, be careful with this: "with great power comes great responsibility" 🕸

What about middleware?

We have some 😎 Here's an example with gorilla/mux router (but feel free to use any other router). Basically, it's an extension of the very first example with the weather controller, but this time we add Request beans and access them via request's context. Also, this example demonstrates how DI can automatically close resources for you (DB connection in this case). The proper error handling is, again, omitted for simplicity.

controllers/weather_controller.go

package controllers

import (
	"database/sql"
	"di-demo/services"
	"github.com/goioc/di"
	"net/http"
)

type WeatherController struct {
	// note that injection works even with unexported fields
	weatherService *services.WeatherService `di.inject:"weatherService"`
}

func (wc *WeatherController) Weather(w http.ResponseWriter, r *http.Request) {
	dbConnection := r.Context().Value(di.BeanKey("dbConnection")).(*sql.Conn)
	city := r.URL.Query().Get("city")
	_, _ = dbConnection.ExecContext(r.Context(), "insert into log values (?, ?, datetime('now'))", city, r.RemoteAddr)
	weather, _ := wc.weatherService.Weather(city)
	_, _ = w.Write([]byte(*weather))
}

controllers/index_controller.go

package controllers

import (
	"database/sql"
	"fmt"
	"github.com/goioc/di"
	"net/http"
	"strings"
	"time"
)

type IndexController struct {
}

func (ic *IndexController) Log(w http.ResponseWriter, r *http.Request) {
	dbConnection := r.Context().Value(di.BeanKey("dbConnection")).(*sql.Conn)
	rows, _ := dbConnection.QueryContext(r.Context(), "select * from log")
	columns, _ := rows.Columns()
	_, _ = w.Write([]byte(strings.ToUpper(fmt.Sprintf("Requests log: %v\n\n", columns))))
	for rows.Next() {
		var city string
		var ip string
		var dateTime time.Time
		_ = rows.Scan(&city, &ip, &dateTime)
		_, _ = w.Write([]byte(fmt.Sprintln(city, "\t", ip, "\t", dateTime)))
	}
}

init.go

package main

import (
	"context"
	"database/sql"
	"di-demo/controllers"
	"di-demo/services"
	"github.com/goioc/di"
	"os"
	"reflect"
)

func init() {
	_, _ = di.RegisterBean("weatherService", reflect.TypeOf((*services.WeatherService)(nil)))
	_, _ = di.RegisterBean("indexController", reflect.TypeOf((*controllers.IndexController)(nil)))
	_, _ = di.RegisterBean("weatherController", reflect.TypeOf((*controllers.WeatherController)(nil)))
	_, _ = di.RegisterBeanFactory("db", di.Singleton, func() (interface{}, error) {
		_ = os.Remove("./di-demo.db")
		db, _ := sql.Open("sqlite3", "./di-demo.db")
		db.SetMaxOpenConns(1)
		_, _ = db.Exec("create table log ('city' varchar not null, 'ip' varchar not null, 'time' datetime not null)")
		return db, nil
	})
	_, _ = di.RegisterBeanFactory("dbConnection", di.Request, func() (interface{}, error) {
		db, _ := di.GetInstanceSafe("db")
		return db.(*sql.DB).Conn(context.TODO())
	})
	_ = di.InitializeContainer()
}

main.go

package main

import (
	"di-demo/controllers"
	"github.com/goioc/di"
	"github.com/gorilla/mux"
	_ "github.com/mattn/go-sqlite3"
	"net/http"
)

func main() {
	router := mux.NewRouter()
	router.Use(di.Middleware)
	router.Path("/").HandlerFunc(di.GetInstance("indexController").(*controllers.IndexController).Log)
	router.Path("/weather").Queries("city", "{*?}").HandlerFunc(di.GetInstance("weatherController").(*controllers.WeatherController).Weather)
	_ = http.ListenAndServe(":8080", router)
}

Okaaay... More examples?

Please, take a look at the unit-tests for more examples.

Comments
  • [Feature request] register&inject bean with named group

    [Feature request] register&inject bean with named group

    register: func RegisterBeanWithGroup(beanID string, beanGroup string, beanType reflect.Type) func RegisterBeanInstance(beanID string, beanGroup string, beanInstance interface{}) inject: HandlerList []Handler `group:"server,flatten"`

    reference: https://pkg.go.dev/go.uber.org/dig#hdr-Value_Groups

    we think this feature is very useful, thanks !

  • [Feature request] Autowiring  beans into slice or map depending on the interface

    [Feature request] Autowiring beans into slice or map depending on the interface

    It would be very useful to autowire beans of the specific interface into the []Interface or map[string]Interface.

    Spring Java examples:

    @Autowired
    private Map<String, Interface> services;
    
    @Autowired
    private List<Interface> services;
    

    Want to have something like in go:

    type Service struct {
         map[string]Interface services `di.mapBeans:"Interface"`
         []Interface services `di.sliceBeans:"Interface"`
    }
    
    
  • Bump github.com/stretchr/testify from 1.7.0 to 1.8.1

    Bump github.com/stretchr/testify from 1.7.0 to 1.8.1

    Bumps github.com/stretchr/testify from 1.7.0 to 1.8.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Bump github.com/stretchr/testify from 1.7.0 to 1.8.0

    Bump github.com/stretchr/testify from 1.7.0 to 1.8.0

    Bumps github.com/stretchr/testify from 1.7.0 to 1.8.0.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Bump github.com/stretchr/testify from 1.7.0 to 1.7.1

    Bump github.com/stretchr/testify from 1.7.0 to 1.7.1

    Bumps github.com/stretchr/testify from 1.7.0 to 1.7.1.

    Commits
    • 083ff1c Fixed didPanic to now detect panic(nil).
    • 1e36bfe Use cross Go version compatible build tag syntax
    • e798dc2 Add docs on 1.17 build tags
    • 83198c2 assert: guard CanConvert call in backward compatible wrapper
    • 087b655 assert: allow comparing time.Time
    • 7bcf74e fix msgAndArgs forwarding
    • c29de71 add tests for correct msgAndArgs forwarding
    • f87e2b2 Update builds
    • ab6dc32 fix linting errors in /assert package
    • edff5a0 fix funtion name
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Fail to inject dependencies

    Fail to inject dependencies

    Hi @dtitov , I'm trying to use your package but I have an issue on the initialize part no one of my dependency are injected. I think misunderstand something but I don't find the issue maybe you can explain me what I miss.

    I'm trying to do:

                         |---> RepoA -|
    db client ---> |---> RepoB -| ----> ServiceA
                         |---> RepoC -|
    
    

    I'm creating a db client and injecting it in different repo (responsible of the data) and then these repo will be injecting in one or many services (responsible of the business logic)

    I share you some extract of my golang code.

    Some struct when I'm trying to do DI:

    type UserRepository struct {
    	CqlClient cql.CqlClient `di.inject:"CqlClient"`
    }
    
    type UserService struct {
    	UserRepo          *repository.UserRepository          `di.inject:"UserRepository"`
    	CommunicationRepo *repository.CommunicationRepository `di.inject:"CommunicationRepository"`
    	AuthRepo          *repository.AuthRepository          `di.inject:"AuthRepository"`
    }
    
    
    

    Registration of my beans:

    repositories := map[string]interface{}{
    	"UserRepository":          &repository.UserRepository{},
    	"CommunicationRepository": &repository.CommunicationRepository{},
    	"AuthRepository":          &repository.AuthRepository{},
    }
    
     // skip code of the init of cqlClient
    
    _, err = di.RegisterBeanInstance("CqlClient", cqlClient)
    if err != nil {
    	l.Fatalw(context.Background(), err.Error())
    }
    
    for k, v := range repositories {
    	_, err = di.RegisterBeanInstance(k, v)
    	if err != nil {
    		l.Fatalw(context.Background(), err.Error())
    	}
    }
    

    I'm calling the function InitializeContainer

    err = di.InitializeContainer()
    if err != nil {
    	l.Fatalw(context.Background(), err.Error())
    }
    defer di.Close()
    

    the di.Close() is called only when my server is shutdown.

    Some prints where I can see the injection is not done:

    fmt.Println(di.GetBeanScopes())
    
    map[AddressService:singleton AuthRepository:singleton CommunicationRepository:singleton CqlClient:singleton UserRepository:singleton UserService:singleton]
    
    fmt.Println(di.GetBeanTypes())
    
    map[AddressService:*address.AddressService AuthRepository:*repository.AuthRepository CommunicationRepository:*repository.CommunicationRepository CqlClient:*cql.CqlManager UserRepository:*repository.UserRepository UserService:*user.UserService]
    
    fmt.Println(di.GetInstance("CqlClient"))
    
    &{<nil> 0xc0003ec380 0xc00011c008 [x-user-uuid x-app-platform x-app-version x-app-build x-request-id uber-trace-id] 0xc0000ae588 <nil> []}
    
    fmt.Println(di.GetInstance("UserRepository"))
    
    &{<nil>}
    
    fmt.Println(di.GetInstance("UserService"))
    
    &{<nil> <nil> <nil>}
    
  • Increase test coverage

    Increase test coverage

    1. Current results according to codecov is 91%.
    2. Here is new results from IDEA: image

    All changes:

    • [x] Added tests to increase code coverage. Primarily for error case scenarios.
    • [x] RegisterBeanFactory with overwrite case -- i was thinking on adding beanFactory to 'beans' map, but after some time i realized that in this case in createSingletonInstances there will be 2 calls to beanFactory. Therefore i created TestBeanFactoryCalledOnce to avoid such a problem in case of refactoring in future -- original testing for that fix is added in test TestRegisterBeanFactoryWithOverwriting
    • [x] Added possible TODO (improvement) //todo validation code part can be moved above for fail-fast purposes
  • Add CodeQL workflow for GitHub code scanning

    Add CodeQL workflow for GitHub code scanning

    Hi goioc/di!

    This is a one-off automatically generated pull request from LGTM.com :robot:. You might have heard that we’ve integrated LGTM’s underlying CodeQL analysis engine natively into GitHub. The result is GitHub code scanning!

    With LGTM fully integrated into code scanning, we are focused on improving CodeQL within the native GitHub code scanning experience. In order to take advantage of current and future improvements to our analysis capabilities, we suggest you enable code scanning on your repository. Please take a look at our blog post for more information.

    This pull request enables code scanning by adding an auto-generated codeql.yml workflow file for GitHub Actions to your repository — take a look! We tested it before opening this pull request, so all should be working :heavy_check_mark:. In fact, you might already have seen some alerts appear on this pull request!

    Where needed and if possible, we’ve adjusted the configuration to the needs of your particular repository. But of course, you should feel free to tweak it further! Check this page for detailed documentation.

    Questions? Check out the FAQ below!

    FAQ

    Click here to expand the FAQ section

    How often will the code scanning analysis run?

    By default, code scanning will trigger a scan with the CodeQL engine on the following events:

    • On every pull request — to flag up potential security problems for you to investigate before merging a PR.
    • On every push to your default branch and other protected branches — this keeps the analysis results on your repository’s Security tab up to date.
    • Once a week at a fixed time — to make sure you benefit from the latest updated security analysis even when no code was committed or PRs were opened.

    What will this cost?

    Nothing! The CodeQL engine will run inside GitHub Actions, making use of your unlimited free compute minutes for public repositories.

    What types of problems does CodeQL find?

    The CodeQL engine that powers GitHub code scanning is the exact same engine that powers LGTM.com. The exact set of rules has been tweaked slightly, but you should see almost exactly the same types of alerts as you were used to on LGTM.com: we’ve enabled the security-and-quality query suite for you.

    How do I upgrade my CodeQL engine?

    No need! New versions of the CodeQL analysis are constantly deployed on GitHub.com; your repository will automatically benefit from the most recently released version.

    The analysis doesn’t seem to be working

    If you get an error in GitHub Actions that indicates that CodeQL wasn’t able to analyze your code, please follow the instructions here to debug the analysis.

    How do I disable LGTM.com?

    If you have LGTM’s automatic pull request analysis enabled, then you can follow these steps to disable the LGTM pull request analysis. You don’t actually need to remove your repository from LGTM.com; it will automatically be removed in the next few months as part of the deprecation of LGTM.com (more info here).

    Which source code hosting platforms does code scanning support?

    GitHub code scanning is deeply integrated within GitHub itself. If you’d like to scan source code that is hosted elsewhere, we suggest that you create a mirror of that code on GitHub.

    How do I know this PR is legitimate?

    This PR is filed by the official LGTM.com GitHub App, in line with the deprecation timeline that was announced on the official GitHub Blog. The proposed GitHub Action workflow uses the official open source GitHub CodeQL Action. If you have any other questions or concerns, please join the discussion here in the official GitHub community!

    I have another question / how do I get in touch?

    Please join the discussion here to ask further questions and send us suggestions!

  • Bump github.com/sirupsen/logrus from 1.8.1 to 1.9.0

    Bump github.com/sirupsen/logrus from 1.8.1 to 1.9.0

    Bumps github.com/sirupsen/logrus from 1.8.1 to 1.9.0.

    Commits
    • f8bf765 Merge pull request #1343 from sirupsen/dbd-upd-dep
    • ebc9029 update dependencies
    • 56c843c Merge pull request #1337 from izhakmo/fix-cve
    • 41b4ee6 update gopkg.in/yaml.v3 to v3.0.1
    • f98ed3e Merge pull request #1333 from nathanejohnson/bumpxsys
    • 2b8f60a bump version of golangci-lint
    • 0db10ef bump version of golang.org/x/sys dependency
    • 85981c0 Merge pull request #1263 from rubensayshi/fix-race
    • 79c5ab6 Merge pull request #1283 from sirupsen/dbd-log-doc
    • 5f8c666 Improve Log methods documentation
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Bump github.com/stretchr/testify from 1.7.0 to 1.7.5

    Bump github.com/stretchr/testify from 1.7.0 to 1.7.5

    Bumps github.com/stretchr/testify from 1.7.0 to 1.7.5.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Bump github.com/stretchr/testify from 1.7.0 to 1.7.4

    Bump github.com/stretchr/testify from 1.7.0 to 1.7.4

    Bumps github.com/stretchr/testify from 1.7.0 to 1.7.4.

    Commits
    • 48391ba Fix panic in AssertExpectations for mocks without expectations (#1207)
    • 840cb80 arrays value types in a zero-initialized state are considered empty (#1126)
    • 07dc7ee Bump actions/setup-go from 3.1.0 to 3.2.0 (#1191)
    • c33fc8d Bump actions/checkout from 2 to 3 (#1163)
    • 3c33e07 Added Go 1.18.1 as a build/supported version (#1182)
    • e2b56b3 Bump github.com/stretchr/objx from 0.1.0 to 0.4.0
    • 41453c0 Update gopkg.in/yaml.v3
    • 285adcc Update go versions in build matrix
    • 6e7fab4 Bump actions/setup-go from 2 to 3.1.0
    • 106ec21 use RWMutex
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
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

Sep 27, 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

Oct 13, 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

Oct 16, 2022
🛠 A full-featured dependency injection container for go programming language.

DI Dependency injection for Go programming language. Tutorial | Examples | Advanced features Dependency injection is one form of the broader technique

Dec 31, 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

Jan 1, 2023
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

Dec 25, 2022
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

Jan 3, 2023
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

Sep 27, 2022
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

Jun 1, 2022
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

Jan 2, 2023
Generated dependency injection containers in go (golang)
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

Dec 22, 2022
golang-runtime-di is a framework for runtime dependency injection in go

golang-runtime-di description golang-runtime-di is a framework for runtime dependency injection in go. usage quickstart add it to your go.mod: go get

Aug 1, 2022
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

Dec 29, 2022
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.

Jan 6, 2023
two scripts written in golang that will help you recognize dependency confusion.
two scripts written in golang that will help you recognize dependency confusion.

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

Mar 3, 2022
A builder 🔨 for binding evil program 😈 and normal document 🐣
A builder 🔨 for binding evil program 😈 and normal document 🐣

GoFileBinder A builder ?? for binding evil program ?? and normal document ?? Usage Clone this repo and build GoFileBinder.go first, then start: ./GoFi

Dec 12, 2022
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

Oct 31, 2021
🦄🌈 YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go.
🦄🌈 YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go.

???? YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go. Support Nacos ,Consoul ,Etcd ,Eureka ,kubernetes.

Jan 4, 2023
Code your next Go web project with (a) Mojito! No matter if its an API or a website, go-mojito assists you with dependency injection, simple routing, custom request / response objects and template rendering
 Code your next Go web project with (a) Mojito! No matter if its an API or a website, go-mojito assists you with dependency injection, simple routing, custom request / response objects and template rendering

Go-Mojito is a super-modular library to bootstrap your next Go web project. It can be used for strict API-only purposes as well as server-side renderi

May 1, 2022
Simple Dependency Injection Container
Simple Dependency Injection Container

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

Sep 27, 2022