go-kid/ioc dependency injection framework with development, debugging, and testing skills
npx claudepluginhub go-kid/iocDevelopment skills for the go-kid/ioc dependency injection framework
English | 中文
go-kid/ioc is a Go runtime dependency injection (IoC/DI) framework based on tag + interface.
wire tag)
value / prop / prefix tags)
${...}#{...} (arithmetic, logical, conditional, collection operations)context.Context lifecycle support: WithContext variants for all lifecycle interfacesioc.Provide[T] validates return type at registration timelog/slog adapter support: Integrate with Go's structured loggingRequires Go 1.21+.
go get github.com/go-kid/ioc
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.
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 typetype Component struct {
Name string
}
type App struct {
C *Component `wire:""` // injected by *Component 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
}
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
}
When an interface has multiple implementations, the container selects by priority:
WirePrimary interface (primary)Naming())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
}
type App struct {
All []Interface `wire:""` // all Interface implementations
}
prefix: Bind Config Prefixtype 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 / Expressionstype T struct {
DSN string `value:"${db.dsn}"` // config placeholder
Sum int `value:"#{1+2}"` // expression
Str string `value:"foo"` // literal
}
prop: Sugar for valuetype DBConfig struct {
DSN string `prop:"db.dsn"` // equivalent to value:"${db.dsn}"
}
${...}: Configuration placeholder, reads value from config#{...}: Expression evaluation, supports arithmetic, logical, conditional, collection operationsExample:
Official prompts.chat marketplace - AI prompts, skills, and tools for Claude Code
Open Design — local-first design app exposed to coding agents over MCP. Install once with your agent's plugin command and projects/files/skills are reachable through stdio.
Behavioral guidelines to reduce common LLM coding mistakes, derived from Andrej Karpathy's observations