{"id":27044796,"url":"https://github.com/berkaroad/ioc","last_synced_at":"2025-04-05T05:30:08.527Z","repository":{"id":57637973,"uuid":"62230989","full_name":"berkaroad/ioc","owner":"berkaroad","description":"Inversion of Control (IoC)","archived":false,"fork":false,"pushed_at":"2023-10-29T14:24:04.000Z","size":52,"stargazers_count":26,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-06-20T08:20:47.639Z","etag":null,"topics":["inject","ioc","singleton","transient"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/berkaroad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-29T14:11:01.000Z","updated_at":"2023-10-04T11:10:07.000Z","dependencies_parsed_at":"2024-06-19T01:27:36.705Z","dependency_job_id":"251e2ba3-5562-4320-b49e-b8b2236871f9","html_url":"https://github.com/berkaroad/ioc","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkaroad%2Fioc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkaroad%2Fioc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkaroad%2Fioc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkaroad%2Fioc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/berkaroad","download_url":"https://codeload.github.com/berkaroad/ioc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247293915,"owners_count":20915327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["inject","ioc","singleton","transient"],"created_at":"2025-04-05T05:30:07.873Z","updated_at":"2025-04-05T05:30:08.475Z","avatar_url":"https://github.com/berkaroad.png","language":"Go","readme":"# ioc\n\nInversion of Control (IoC)\n\n## Feature\n\n* 1) Support service as singleton and transient\n\n* 2) Support resolve service by parent if not found in current\n\n* 3) Support inject to function or *struct with services that has registered\n\n  Should add struct tag 'ioc-inject:\"true\"' to field if want to be injected, but field type `ioc.Resolver` is not necessary.\n\n* 4) Support override exists service\n\n  Register to parent's container, and then register to current's to override parent's.\n\n* 5) Support inject to singleton instance automatically\n\n  Inject to singleton instance and it's initialize method `Initialize(XXX)` or another one which the returns of method `InitializeMethodName() string` automatically.\n\n  It will use zero value instead of panic if depended service not registerd.\n\n## Usage\n\n```go\npackage main\n\nimport (\n    \"github.com/berkaroad/ioc\"\n)\n\ntype Interface1 interface {\n    GetC2Name() string\n}\n\ntype Interface2 interface {\n    GetName() string\n}\n\ntype Class1 struct {\n    Resolver ioc.Resolver\n    C2       *Class2 `ioc-inject:\"true\"`\n}\n\nfunc (c *Class1) GetC2Name() string {\n    return c.C2.Name\n}\n\ntype Class2 struct {\n    Name     string\n    resolver ioc.Resolver\n}\n\nfunc (c *Class2) GetName() string {\n    return c.Name\n}\n\nfunc (c *Class2) Initialize(resolver ioc.Resolver) string {\n    c.resolver = resolver\n    return c.Name\n}\n\ntype Interface3 interface {\n    GetName() string\n}\n\ntype Class3 struct {\n    Name     string\n    resolver ioc.Resolver\n}\n\nfunc (c *Class3) GetName() string {\n    return \"Class3-\" + c.Name\n}\n\n// specific custom initialize method name\nfunc (c *Class3) InitializeMethodName() string {\n    return \"MyInitialize\"\n}\n\n// custom initialize method\nfunc (c *Class2) MyInitialize(resolver ioc.Resolver) string {\n    c.resolver = resolver\n    return c.Name\n}\n\ntype Class4 struct {\n    Name     string\n}\n\nfunc (c *Class4) GetName() string {\n    return \"Class3-\" + c.Name\n}\n\nfunc main() {\n    // register service to *struct\n    ioc.AddSingleton[*Class2](\u0026Class2{Name: \"Jerry Bai\"})\n    ioc.AddTransient[*Class1](func() *Class1 {\n        var svc Class1\n        // inject to *struct\n        ioc.Inject(\u0026svc)\n    }\n\n    // register service to interface.\n    ioc.AddSingleton[Interface2](\u0026Class2{Name: \"Jerry Bai\"})\n    ioc.AddTransient[Interface1](func() Interface1 {\n        var svc Class1\n        // inject to *struct\n        ioc.Inject(\u0026svc)\n    }\n\n    // get service from ioc\n    c1 := ioc.GetService[*Class1]\n    c2 := ioc.GetService[*Class2]\n    i1 := ioc.GetService[Interface1]\n    i2 := ioc.GetService[Interface2]\n\n    // inject to function\n    ioc.Inject(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, resolver ioc.Resolver) {\n        println(\"c1.C2Name=\", c1.C2.Name)\n        println(\"c2.Name=\", c2.Name)\n        println(\"i1.GetC2Name=()\", i1.GetC2Name())\n        println(\"i2.GetName=()\", i2.GetName())\n    })\n\n    // override exists service\n    c := ioc.New()\n    ioc.SetParent(c)\n    ioc.AddSingletonToC[Interface3](c, \u0026Class3{Name: \"Jerry Bai\"}) // add service to parent's container\n    i3 := ioc.GetService[Interface3]() // *Class3, 'Interface3' only exists in parent's container\n    ioc.AddSingleton[Interface3](\u0026Class4{Name: \"Jerry Bai\"}) // add service to global's container\n    i3 = ioc.GetService[Interface3]() // *Class4, 'Interface3' exists in both global and parent's container\n}\n```\n\n## Benchmark\n\n```sh\ngo test -run=none -count=1 -benchtime=1000000x -benchmem -bench=. ./...\n\ngoos: linux\ngoarch: amd64\npkg: github.com/berkaroad/ioc\ncpu: AMD Ryzen 7 5800H with Radeon Graphics         \nBenchmarkGetSingletonService-4           1000000                26.16 ns/op            0 B/op          0 allocs/op\nBenchmarkGetTransientService-4           1000000               370.9 ns/op            48 B/op          1 allocs/op\nBenchmarkGetTransientServiceNative-4     1000000               131.9 ns/op            48 B/op          1 allocs/op\nBenchmarkInjectToFunc-4                  1000000               659.5 ns/op           144 B/op          5 allocs/op\nBenchmarkInjectToFuncNative-4            1000000                89.26 ns/op            0 B/op          0 allocs/op\nBenchmarkInjectToStruct-4                1000000               311.7 ns/op             0 B/op          0 allocs/op\nBenchmarkInjectToStructNative-4          1000000                87.64 ns/op            0 B/op          0 allocs/op\nPASS\nok      github.com/berkaroad/ioc        1.686s\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberkaroad%2Fioc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fberkaroad%2Fioc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberkaroad%2Fioc/lists"}