ClaudeCodeMod

All shelves / Marketplaces

go-kid/ioc

go-kid/ioc · 1 stars · 1 plugin

Marketplace

Install

In Claude Code
/plugin marketplace add go-kid/ioc

Run inside Claude Code, then install plugins from it. Check the repo's README before you run it.

Open the repo

Plugins 1

After adding the marketplace, install one with /plugin install <name>@go-kid-ioc.

  1. 1iocgo-kid/ioc dependency injection framework with comprehensive skills for development (ioc-dev), debugging (ioc-debug), and testing/extension (ioc-test)/plugin install ioc@go-kid-iocv1.0.0library-reference

Files

README.md

go-kid/ioc

English | 中文

go-kid/ioc is a Go runtime dependency injection (IoC/DI) framework based on tag + interface.

✨ Features

  • Component Dependency Injection (wire tag)
    • Inject by pointer type, interface type, or component name
    • Multiple implementation selection strategies (Primary/Qualifier)
    • Inject into interface slices/arrays
  • Configuration Injection (value / prop / prefix tags)
    • Multiple configuration sources (command-line args, files, raw content)
    • Configuration placeholders ${...}
    • Expression evaluation #{...} (arithmetic, logical, conditional, collection operations)
  • Lifecycle Management: ApplicationRunner, CloserComponent, LazyInitComponent
  • context.Context lifecycle support: WithContext variants for all lifecycle interfaces
  • Scope mechanism: Singleton/Prototype
  • Conditional component registration: Register components based on runtime conditions
  • Application event mechanism: Publish and listen for application events
  • log/slog adapter support: Integrate with Go's structured logging

📦 Installation

Requires Go 1.21+.

go get github.com/go-kid/ioc

🚀 Quick Start

package main

import (
	"fmt"
	"github.com/go-kid/ioc"
)

// Component to be injected
type ComponentA struct {
	Name string
}

func (a *ComponentA) GetName() string {
	return a.Name
}

// Target struct that depends on ComponentA
type App struct {
	ComponentA *ComponentA `wire:""` // pointer + exported field + wire tag
}

func main() {
	a := new(App)

	// Register components
	ioc.Register(a)
	ioc.Register(&ComponentA{Name: "Comp-A"})

	// Run the framework
	_, err := ioc.Run()
	if err != nil {
		panic(err)
	}

	// Output: "Comp-A"
	fmt.Println(a.ComponentA.GetName())
}

Key points: Dependency fields must be exported (start with uppercase) and use wire:"" to declare injection.

📖 Documentation

1. Component Dependency Injection (wire tag)

Component injection is controlled via tag: wire:"<name>,arg1=xxx,arg2=yyy"

  • <name>: optional, inject by component name
  • ,arg=...: optional extra arguments (e.g., qualifier)
  • wire:"" (empty) means inject by type

Inject by Pointer Type

type Component struct {
	Name string
}

type App struct {
	C *Component `wire:""` // injected by *Component type
}

Inject by Interface Type

type IComponent interface {
	GetName() string
}

type ComponentA struct{ Name string }
func (a *ComponentA) GetName() string { return a.Name }

type App struct {
	C IComponent `wire:""` // inject by interface type
}

Inject by Name

Implement NamingComponent interface to define component names:

type ComponentA struct {
	Name          string
	componentName string
}

func (a *ComponentA) Naming() string { return a.componentName }

type App struct {
	ByName IComponent `wire:"comp-A"` // inject by component name
}

Multiple Implementation Selection Strategy

When an interface has multiple implementations, the container selects by priority:

  1. Components implementing WirePrimary interface (primary)
  2. Components without alias (not implementing Naming())
  3. One will be chosen (order not guaranteed)

Using Primary marker:

type ComponentA struct {
	Name string
	definition.WirePrimaryComponent // embed Primary component
}

Using Qualifier:

type ComponentA struct {
	qualifier string
}

func (a *ComponentA) Qualifier() string { return a.qualifier }

type App struct {
	C IComponent `wire:",qualifier=comp-A"` // use qualifier
}

Inject into Slice/Array

type App struct {
	All []Interface `wire:""` // all Interface implementations
}

2. Configuration Injection

prefix: Bind Config Prefix

type configA struct {
	B int   `yaml:"b"`
	C []int `yaml:"c"`
}

type App struct {
	A *configA `prefix:"a"` // bind config prefix "a"
}

Configuration (YAML):

a:
  b: 123
  c: [1,2,3,4]

value: Literals / Placeholders / Expressions

type T struct {
	DSN string `value:"${db.dsn}"`           // config placeholder
	Sum int    `value:"#{1+2}"`               // expression
	Str string `value:"foo"`                  // literal
}

prop: Sugar for value

type DBConfig struct {
	DSN string `prop:"db.dsn"` // equivalent to value:"${db.dsn}"
}

Placeholders and Expressions

  • ${...}: Configuration placeholder, reads value from config
  • #{...}: Expression evaluation, supports arithmetic, logical, conditional, collection operations

Example:

type T struct {
	Arithmetic  int    `value:"#{1+(1*2)}"`                      // 3
	Comparison  bool   `value:"#{1/1==1}"`                       // true
	Conditional string `value:"#{1>2?'a':'b'}"`                  // "b"
	WithConfig  int    `value:"#{${number.val1}+${number.val2}}"` // use config
}

3. Application Startup

Style 1: Use ioc.Run / ioc.Register

ioc.Register(a)
ioc.Register(&ComponentA{Name: "Comp-A"})
_, err := ioc.Run()

Style 2: Work with app.App Directly

application := app.NewApp()
err := application.Run(
	app.SetComponents(...),
	app.SetConfigLoader(loader.NewFileLoader("config.yaml")),
	app.SetConfigBinder(binder.NewViperBinder("yaml")),
)

4. Lifecycle Interfaces

  • ApplicationRunner: executed after all components are refreshed
  • CloserComponent: Close() called when app stops
  • LazyInitComponent: marked as lazy initialization
  • PriorityComponent: controls post-processor execution order
  • InitializeComponentWithContext / InitializingComponentWithContext: context-aware Init/AfterPropertiesSet
  • ApplicationRunnerWithContext: context-aware Run
  • CloserComponentWithContext: context-aware Close
  • DestructionAwareComponentPostProcessor: callback before created singletons are destroyed
  • ScopeComponent: control component scope (singleton/prototype)
  • ConditionalComponent: conditional registration based on runtime conditions
  • ApplicationEventListener / ApplicationEventPublisher: event mechanism

5. Context Support

All lifecycle interfaces have WithContext variants. Components can implement them to receive a context.Context for timeout control, cancellation propagation, etc.

// Run the framework with a context
app, err := ioc.RunWithContext(ctx)

// Set a shutdown timeout
_, err := ioc.Run(app.SetShutdownTimeout(30 * time.Second))

Context-aware lifecycle interfaces:

// InitializeComponentWithContext (replaces InitializeComponent)
func (c *MyComp) Init(ctx context.Context) error { return nil }

// InitializingComponentWithContext (replaces InitializingComponent)
func (c *MyComp) AfterPropertiesSet(ctx context.Context) error { return nil }

// ApplicationRunnerWithContext (can coexist with ApplicationRunner)
func (r *MyRunner) RunWithContext(ctx context.Context) error { return nil }

// CloserComponentWithContext (can coexist with CloserComponent)
func (c *MyComp) CloseWithContext(ctx context.Context) error { return nil }

Note: Init(ctx) and AfterPropertiesSet(ctx) have the same method names as their base interfaces but different signatures, so a component implements one or the other. RunWithContext and CloseWithContext use distinct method names, allowing a component to implement both the original and context-aware versions.

6. Scope

Control component scope by implementing ScopeComponent:

  • Singleton (default): single instance in the container
  • Prototype: a new instance is shallow-copied from the registered template and fully populated on every access; it is not eagerly created
import "github.com/go-kid/ioc/definition"

type MyPrototype struct{}

func (p *MyPrototype) Scope() string { return definition.ScopePrototype }

7. Conditional Registration

Implement ConditionalComponent to decide at runtime whether a component should be created:

import "github.com/go-kid/ioc/definition"

type MyComp struct{}

func (c *MyComp) Condition(ctx definition.ConditionContext) bool {
	return ctx.HasComponent("dependency")
}

8. Events

Publish and listen for application events to enable loose coupling between components:

import "github.com/go-kid/ioc/definition"

// Listen for events
type MyListener struct{}

func (l *MyListener) OnEvent(event definition.ApplicationEvent) error {
	// handle event
	return nil
}

Built-in events: ComponentCreatedEvent after a component is initialized, ApplicationStartedEvent after runners complete, and ApplicationClosingEvent before shutdown. On shutdown, destruction-aware post-processors run for created singletons in reverse creation order, then closer components run concurrently. Prototype instances are owned by their callers and are not destroyed automatically.

🏗️ Architecture

┌─────────────────────────────────────────────────────────────────┐
│                          app.App                                 │
│  ┌──────────────────┐              ┌──────────────────┐         │
│  │ Component Factory│              │    Configure     │         │
│  └────────┬─────────┘              └────────┬─────────┘         │
│           │                                  │                   │
│           │                                  │                   │
│  ┌────────▼─────────┐              ┌────────▼─────────┐       │
│  │ DefinitionRegistry│              │      Loader       │       │
│  │ SingletonRegistry│              │  (args/file/raw)  │       │
│  └────────┬─────────┘              └────────┬─────────┘       │
│           │                                  │                   │
│           │ register                         │                   │
│  ┌────────▼─────────┐              ┌────────▼─────────┐       │
│  │ComponentDefinition│              │      Binder       │       │
│  └────────┬─────────┘              │      (viper)       │       │
│           │                         └───────────────────┘       │
│           │ create                                               │
│  ┌────────▼─────────┐                                           │
│  │     Instance     │                                           │
│  └────────┬─────────┘                                           │
│           │                                                      │
│  ┌────────▼──────────────────────────────────────────┐          │
│  │            PostProcessors                          │          │
│  │  ┌────────────────────────────────────────────┐   │          │
│  │  │ • LoggerAware                               │   │          │
│  │  │ • ConfigQuoteAware ${...}                   │   │          │
│  │  │ • ExpressionTagAware #{...}                  │   │          │
│  │  │ • PropertiesAware prefix                    │   │          │
│  │  │ • ValueAware value/prop                     │   │          │
│  │  │ • DependencyAware wire                      │   │          │
│  │  │ • DependencyFunctionAware func               │   │          │
│  │  └────────────────────────────────────────────┘   │          │
│  └──────────────────────────────────────────────────┘          │
└─────────────────────────────────────────────────────────────────┘

Config Flow: Binder → ConfigQuoteAware, PropertiesAware, ValueAware, ExpressionTagAware

📚 Examples & Tests

  • Example projects: examples/debug_demo, examples/post_processor
  • Post processor example: examples/post_processor/
  • Performance tools: cmd/performance_analyst/
  • Unit tests: unittest/component/builtin_inject/*, unittest/configure/*

Run tests:

go test ./...

Pull requests and pushes to main also run the race detector, go vet, go build, and enforce at least 75% repository-wide statement coverage in GitHub Actions.

📄 License

MIT License

🤝 Contributing

Contributions via Issues / PRs are welcome. Please ensure go test ./... passes before submitting.

Facts

Kind
Marketplace
Repo
go-kid/ioc
Group
Uncategorized
Stars
1
Marketplace name
go-kid-ioc
Owner
go-kid
License
Apache-2.0
Language
Go
Created
2023-04-04
Last push
2026-09-09
Plugins
1

More on this shelf

  1. 1obra/superpowersobra/superpowersAn agentic skills framework & software development methodology that works.297.9k
  2. 2affaan-m/everything-claude-codeaffaan-m/ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.277.5k
  3. 3anthropics/skillsanthropics/skillsPublic repository for Agent Skills180.6k
  4. 4f/prompts.chatf/prompts.chatf.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.172.7k
  5. 5anthropics/claude-codeanthropics/claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.150.3k
  6. 6nextlevelbuilder/ui-ux-pro-max-skillnextlevelbuilder/ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.135k