digo

package module
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2023 License: MIT Imports: 13 Imported by: 0

README

English | 简体中文

digo

Note: Go version 1.20+ is required.

An annotation-based tool for compile-time dependency injection in Golang.

Features

  • Use annotations in comments.
  • Automatic code generation.
  • Automatic detection of circular dependencies.
  • Compile-time dependency injection.
  • Automatic initialization.
  • Support for managing instance groups.

Quick Start

For more examples, please refer to: examples.

Write Code and Annotations
package main

import (
	"log"

	"github.com/werbenhu/digo"
)

// @provider({"id":"main.db.url"})
func NewDbUrl() string {
	return "localhost:3306"
}

type Db struct {
	url string
}

// @provider({"id":"main.db"})
// @inject({"param":"url", "id":"main.db.url"})
func NewDb(url string) *Db {
	return &Db{
		url: url,
	}
}

type Redis struct {
}

// @provider({"id":"main.redis"})
func NewRedis() *Redis {
	return &Redis{}
}

type App struct {
	db    *Db
	redis *Redis
}

// @provider({"id":"main.app"})
// @inject({"param":"db", "id":"main.db"})
// @inject({"param":"redis", "id":"main.redis"})
func NewApp(db *Db, redis *Redis) *App {
	return &App{
		db:    db,
		redis: redis,
	}
}

func (a *App) Start() {
	log.Printf("app strat, db:%s\n", a.db.url)
}

func main() {
	app, err := digo.Provide("main.app")
	if err == nil {
		app.(*App).Start()
	}
}
Install digogen Tool
go install github.com/werbenhu/digo/digogen@v1.0.3
Generate Dependency Injection Code

Open the command line and execute the following command. digogen will automatically generate the digo.generated.go source code file based on the annotations.

cd examples/simple
digogen
Run the Code

go run .\digo.generated.go .\main.go

Annotation Details

@provider

The @provider annotation indicates that it is an instance provider, and the instance is a singleton.

  • Example:
// @provider({"id":"main.db"})
  • Supported parameters:
Name Type Required Description
id string Yes The ID of the instance

To obtain an instance, you can use digo.Provide(providerId) to retrieve the instance of a specific provider.

app, err := digo.Provide("main.app")
if err == nil {
	app.(*App).Start()
}

@inject

The @inject annotation indicates injecting an instance into a parameter. The @inject annotation must coexist with either @provider or @group.

  • Example:
// @inject({"param":"db", "id":"main.db"})
  • Supported parameters:
Name Type Required Description
param string Yes Specifies the parameter to inject the instance into
id string Yes Specifies the ID of the instance to be injected
pkg string No Specifies the package to import for the parameter

The pkg parameter is used when you need to import a specific package. For example, if you need to import the package github.com/xxx/tool/v1, you would use the package name as *tool.Struct, not *v1.Struct. In such cases, you need to explicitly specify the import of the github.com/xxx/tool/v1 package.

// @inject({"param":"tool", "id":"main.tool", "pkg":"github.com/xxx/tool/v1"})

@group

The @group annotation indicates registering an instance to a group.

  • Example:
// @group({"id":"main.controllers"})
  • Supported parameters:
Name Type Required Description
id string Yes The ID of the group

To retrieve all instances of a group, you can use digo.Members(groupId) to get all the instances of the group.

ctrls, err := digo.Members("main.controllers")
if err == nil {
    for _, controller := range ctrls {
        // TODO:
    }
}

Documentation

Index

Constants

View Source
const (
	// RegexpText represents the regular expression pattern for parsing annotations.
	RegexpText = `^//\s*@(provider|inject|group)\s*\((.*)\s*\)`
)

Variables

This section is empty.

Functions

func Members

func Members(name string) ([]any, error)

Members returns the group of objects associated with the provided group ID. It returns an error if the group does not exist.

func Provide

func Provide(id string) (any, error)

Provide returns the singleton object associated with the provided ID. It returns an error if the object does not exist.

func RegisterMember

func RegisterMember(groupId string, object any)

RegisterMember registers a member object with the provided group ID.

func RegisterSingleton

func RegisterSingleton(id string, object any)

RegisterSingleton registers a singleton object with the provided ID.

Types

type DiFile

type DiFile struct {
	Name    string
	Package *DiPackage
	Imports map[string]*DiImport
}

DiFile represents a file in Go source code. DiFile 表示一个go源代码的一个文件

func NewDiFile

func NewDiFile(pkg *DiPackage, name string) *DiFile

type DiFunc

type DiFunc struct {
	Name       string
	Injectors  []*Injector
	ProviderId string
	GroupId    string
	Sort       int
	Package    *DiPackage
	File       *DiFile
}

DiFunc represents a function with valid annotations. DiFunc表示被合法的注解的函数

func NewDiFunc

func NewDiFunc(pkg *DiPackage, file *DiFile, name string) *DiFunc

NewDiFunc creates a new DiFunc instance.

type DiFuncs

type DiFuncs []*DiFunc

DiFuncs represents an array of functions with valid annotations. DiFuncs 表示被合法的注解的函数数组

func (DiFuncs) Len

func (idx DiFuncs) Len() int

Len returns the length of the funcs.

func (DiFuncs) Less

func (idx DiFuncs) Less(i, j int) bool

Less compares the elements at positions i and j in the slice and returns true if the element at position i is less than the element at position j.

func (DiFuncs) Sort

func (idx DiFuncs) Sort()

Sort sorts the elements in the slice in reverse order.

func (DiFuncs) Swap

func (idx DiFuncs) Swap(i, j int)

Swap swaps the elements at positions i and j in the funcs.

type DiImport

type DiImport struct {
	Name string // name represents the package name.
	Path string // Path represents the import path.
}

DiImport represents an import statement in Go source code, recording the imported package name and path. DiImport 表示go源代码中的一个improt语句信息,记录引入的包名和别名

type DiPackage

type DiPackage struct {
	Name   string
	Path   string
	Folder string
	Funcs  DiFuncs
	Files  map[string]*DiFile
}

DiPackage represents a package in Go source code. DiPackage 表示一个go源代码的一个包

func NewDiPackage

func NewDiPackage(name string, path string, folder string) *DiPackage

type Generator

type Generator struct {
	Package         *DiPackage
	CalledInitFuncs []ast.Stmt          // Initialization functions for singleton objects
	Fset            *token.FileSet      // FileSet for token positions
	Decls           []ast.Decl          // Functions generated by the provider
	ImportSpecs     map[string]ast.Spec // Packages to be imported

	ManagerPackage    string
	RegisterFunction  string
	ProvideFunction   string
	GroupFunction     string
	GeneratedFileName string
}

Generator is a code generator for dependency injection.

func NewGenerator

func NewGenerator(pkg *DiPackage) *Generator

NewGenerator creates a new Generator with the given path, package name, and filename.

func (*Generator) Do

func (g *Generator) Do()

Do converts the extracted providers and injectors in the current package into Go AST structures and outputs the code to a Go file.

type Injector

type Injector struct {
	ProviderId string `json:"id"` // Id represents the identifier of the provider.
	Pkg        string
	Param      string // Param represents the parameter name.
	Alias      string

	Typ        ast.Expr // Typ represents the type of the parameter.
	Dependency *DiFunc
}

Injector represents an injector parameter.

func (*Injector) GetArgName

func (i *Injector) GetArgName() string

GetArgName returns the variable name of the injector parameter, which is passed to the provider's constructor. GetArgName 返回injector注解的变量名,这个变量用来传递给provider的构造函数

func (*Injector) GetObjName

func (i *Injector) GetObjName() string

GetObjName returns the temporary variable name for the injector parameter, which has the "any" type. GetObjName 返回injector注解的参数的临时变量名,这个变量是any类型.

type Member

type Member struct {
	GroupId string `json:"id"` // GroupId represents the group ID of the member.
}

Member represents a member in a group.

type Parser

type Parser struct {
	Packages []*DiPackage
}

Parser represents a parser for source code parsing. Parser表示解析源码的解析器

func NewParser

func NewParser() *Parser

func (*Parser) Start

func (p *Parser) Start()

Start initiates the annotation analysis, generates Go code, and writes it to files. Start 启动分析注解,并生成go代码,写入到文件中

type Provider

type Provider struct {
	Id string // Id represents the identifier of the provider.
}

Provider represents a provider.

Directories

Path Synopsis
examples
group
This file is generated by digogen.
This file is generated by digogen.
multipackage/controllers
This file is generated by digogen.
This file is generated by digogen.
multipackage/database
This file is generated by digogen.
This file is generated by digogen.
multipackage/models
This file is generated by digogen.
This file is generated by digogen.
simple
This file is generated by digogen.
This file is generated by digogen.

Jump to

Keyboard shortcuts

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