Skip to content

poy/go-dependency-injection

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

go-dependency-injection

Dependency injection in Go

Motivation

I wanted a DI system that allowed solid typing using generics. I also wanted a way that I could do things like routing and CLI subcommands, so I created a way to register a group of types that could then be consumed by something like a router.

Examples

Simple example

package main

import (
	"context"

	"github.com/poy/go-dependency-injection/pkg/injection"
)

type A interface {
	A()
}

type B interface {
	B()
}

func init() {
	injection.Register[A](
		func(ctx context.Context) A {
			return &a{
				b: injection.Resolve[B](ctx),
			}
		},
	)
}

type a struct {
	b B
}

func (a *a) A() {
	println("A()")
	a.b.B()
}

func init() {
	injection.Register[B](
		func(ctx context.Context) B {
			return &b{}
		},
	)
}

type b struct {
}

func (b *b) B() {
	println("B()")
}

func main() {
	ctx := injection.WithInjection(context.Background())
	a := injection.Resolve[A](ctx)
	a.A()
}

CLI with subcommands

This example demonstrates a CLI with subcommands that register themselves. This doesn't show it, however each subcommand should/could be its own file.

package main

import (
	"context"
	"os"

	"github.com/poy/go-dependency-injection/pkg/injection"
	"github.com/spf13/cobra"
)

func main() {
	ctx := injection.WithInjection(context.Background())
	if err := BuildRoot(ctx).ExecuteContext(ctx); err != nil {
		os.Exit(1)
	}
}

type SubCommand *cobra.Command

func BuildRoot(ctx context.Context) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "some-cli",
		Short: "Some CLI",
		Long:  "Some CLI",
		RunE: func(cmd *cobra.Command, args []string) error {
			return cmd.Help()
		},
	}

	for _, subCmd := range injection.Resolve[injection.Group[SubCommand]](ctx).Vals() {
		cmd.AddCommand(subCmd)
	}

	return cmd
}

func init() {
	injection.Register[injection.Group[SubCommand]](
		func(ctx context.Context) injection.Group[SubCommand] {
			return injection.AddToGroup(ctx, buildFooCommand(ctx))
		},
	)
}

func buildFooCommand(ctx context.Context) SubCommand {
	return &cobra.Command{
		Use:  "foo",
		Args: cobra.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			println("Foo")
			return nil
		},
	}
}

About

Dependency injection in Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages