{"id":42609127,"url":"https://github.com/jucardi/go-beans","last_synced_at":"2026-01-29T02:21:13.767Z","repository":{"id":57536388,"uuid":"131357249","full_name":"jucardi/go-beans","owner":"jucardi","description":"Components manager for easy dependency injection","archived":false,"fork":false,"pushed_at":"2021-11-09T22:45:57.000Z","size":1412,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-29T03:08:27.871Z","etag":null,"topics":["bean","beans","dependency-injection","dependency-manager","factory","go","golang","mock","mockito","mocks"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jucardi.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}},"created_at":"2018-04-28T00:44:22.000Z","updated_at":"2024-01-17T14:08:25.000Z","dependencies_parsed_at":"2022-08-28T18:01:17.385Z","dependency_job_id":null,"html_url":"https://github.com/jucardi/go-beans","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/jucardi/go-beans","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-beans","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-beans/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-beans/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-beans/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jucardi","download_url":"https://codeload.github.com/jucardi/go-beans/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-beans/sbom","scorecard":{"id":540753,"data":{"date":"2025-08-11","repo":{"name":"github.com/jucardi/go-beans","commit":"964e5326143419ee33ee577ff54e325ef40cbf54"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/12 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0493 / GHSA-p782-xgp4-8hr8"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T08:09:06.170Z","repository_id":57536388,"created_at":"2025-08-20T08:09:06.170Z","updated_at":"2025-08-20T08:09:06.170Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28860815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T22:56:21.783Z","status":"online","status_checked_at":"2026-01-29T02:00:06.714Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["bean","beans","dependency-injection","dependency-manager","factory","go","golang","mock","mockito","mocks"],"created_at":"2026-01-29T02:21:13.251Z","updated_at":"2026-01-29T02:21:13.759Z","avatar_url":"https://github.com/jucardi.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-beans\n## Components manager for easy dependency injection. Inspired in the Java Spring Framework beans.\n\n`go-beans` is a components manager / components factory that easily allows dependency injection and easily switch these dependencies with other implementations of the components (beans)\n\nFor example, assume we wanted to create an Alerts handler to send alerts on events in a system. There are multiple mechanisms to send out an alert (Email, SMS, chat message, push notification, RSS, etc.).\n\nWe could define a base interface\n\n```Go\ntype IAlertHandler interface {\n    Send(alert *Alert) error\n}\n```\n\nAnd then have multiple implementations of this interface to send an alert via a specific delivery mechanism.\n\n```Go\ntype EmailAlertHandler struct {\n    // some fields here if needed\n}\n\nfunc (e *EmailAlertHandler) Send(alert *Alert) error {\n    // handle some logic to send the SMTP message\n    return nil\n}\n```\n\n\n```Go\ntype SMSAlertHandler intestructrface {\n    // some fields here if needed\n}\n\nfunc (s *SMSAlertHandler) Send(alert *Alert) error {\n    // handle some logic to send the SMS message\n    return nil\n}\n```\n\nUsing the `go-beans` factory, we could register these beans with a name (Eg. \"email\" and \"sms\"), and control which one of them will be used with a simple configuration.\n\n```Go\n// Alert trigger handler\n\nfunc GetHandler() IAlertHandler {\n    // name of the handler to be used. Eg \"email\"\n    alertType := config.AlertType\n    return beans.Resolve((*IAlertHandler)(nil), alertType).(IAlertHandler)\n}\n\n\nfunc sendAlert(alert *Alert) {\n    err := GetHandler().Send(alert)\n    if err != nil {\n        log.Error(err)\n    }\n}\n```\n\nAdditionally, when doing integration testing, the beans factory allows to overwrite a bean that goes by a given name, or a bean that is set as primary, so even using the real bean name, a mock implementation can be hooked into the application, so it can still be tested as a whole.\n\n## How to create a bean?\n\nFor the previous example, this would be an implementation of the `email` alert handler\n\n**`email.go`**\n```Go\npackage email\n\nimport \"some-path-to-the-alerts-package/alerts\"\n\n// The struct that represents the email handler implementation.\ntype EmailAlertHandler struct {\n}\n\n// The method to be implemented\nfunc (e *EmailAlertHandler) Send(alert *Alert) error {\n    return nil\n}\n\nfunc (t *ServiceImpl) init() {\n    // any init logic of the bean.\n}\n\n// Here we define what the bean name will be. We declare it in a constant, so if multiple implementations\n// exist, it is easy to find the proper bean name so the bean can be easily retrieved. If doing multiple\n// implementations, the beans name must be unique\nconst BeanName = \"email\"\n\n// The following like is to validate the implementation of the interface on build, so it do not fail in\n// runtime if a new function was added to the interface and missed to add the implementation in\n// this section.\nvar _ IAlertHandler = (*EmailAlertHandler)(nil)\n\n// In this example we'll use a singleton instance to be registered as the bean.\nvar instance *EmailAlertHandler\n\n// Registering the bean implementation.\nfunc init() {\n\n    // In this example we do a lazy construct of a singleton bean, where the singleton will be\n    // initialized on first use rather than on load of the application.\n    //\n    // The (*IAlertHandler)(nil) is a nil pointer to the bean interface. It is required so the\n    // factory knows what is the bean type so it can properly register it. An alternative to this\n    // approach is to declare pointer to the interface without assigning any value to it, so it\n    // can be passed as an argument.\n    //\n    // Eg.\n    //        var reference *IAlertHandler\n    //\n    //        bean.RegisterFunc(reference, BeanName, func() interface{}) {\n    //\n    beans.RegisterFunc((*IAlertHandler)(nil), BeanName, func() interface{} {\n        instance := \u0026EmailAlertHandler{}\n        instance.init()\n        return instance\n    }, true) // This boolean value indicates that once built for the first time, the instance\n             // should be stored as a singleton, so the next time the Bean is called, the singleton\n             // instance will be returned rather that constructing a new instance.\n}\n```\n\nIn the `alerts` package we could have the following function that will simply retrieve the instance to be used\nso other services will not have to talk to the beans factory directly\n```Go\npackage alerts\n\n// With this singleton function, the primary implementation of the bean can be accessed directly from\n// the package where it was defined, so third party consumers won't have to import the bean package,\n// making it transparent to utilize any implemented service.\nfunc Get() IAlertHandler {\n    return beans.Resolve((*IAlertHandler)(nil), config.AlertType).(IAlertHandler)\n}\n```\n\n## Replacing an existing bean with a mock for testing\n\nIn a test file (or a test utils file that could be used across other consuming services), implement a struct\nof the interface to be used as a mock. In the following example, the mock implementation also has a logic to mock responses and validate calls. This can be extended to be more\n\n**`alerts_test.go`**\n```Go\npackage alerts\n\n/* =========== Mock implementation ============ */\n\ntype MockAlertHandler struct {\n    sendResponse error\n}\n\nfunc (m *MockAlertHandler) Send(alert *Alert) error {\n    return m.sendResponse\n}\n\n// Additional method useful to add a expected response with one of the interface methods are called\nfunc (m *MockAlertHandler) WhenSend(expectedResponse error) {\n    m.sendResponse = expectedResponse\n}\n\nvar (\n    // Ensures the struct implements the interface on compile time, to prevent failures in runtime\n    _ IAlertHandler = (*MockAlertHandler)(nil)\n\n    // The mock instance\n    mock *MockAlertHandler\n)\n\n// To obtain and register a mock implementation.\nfunc Mock() *MockAlert {\n    if mock != nil {\n        return mock\n    }\n\n    mock = \u0026MockAlertHandler{}\n    beans.RegisterFunc((*IAlertHandler)(nil), \"email\", func() interface{} {\n        return mock\n    })\n\n\treturn mock\n}\n\n/* =========== End of Mock implementation ============ */\n\n/* =========== Tests begin here ============ */\n\n// Initialize tests.\nfunc init() {\n    // Setting AllowOverrides to 'true' will allow the beans factory to replace existing beans\n    // with mock implementations.\n    beans.SetAllowOverrides(true)\n}\n\nfunc TestSomething(t *testing.T) {\n    mock := Mock()\n    mock.WhenAlert(errors.New(\"some error\"))\n\n    assert.Equal(t, errors.New(\"some error\"), mock.Send(nil))\n}\n```\n\n##### Quick Start\n\nTo get the most recent source code:\n\n```bash\ngo get github.com/jucardi/go-beans\n```\n\nTo get a specific version:\n\n```bash\ngo get github.com/jucardi/go-beans","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjucardi%2Fgo-beans","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjucardi%2Fgo-beans","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjucardi%2Fgo-beans/lists"}