📚 gontainer/gontainer - Awesome Go Library for Miscellaneous
A YAML-based Dependency Injection container for GO. It supports dependencies' scopes, and auto-detection of circular dependencies. Gontainer is concurrent-safe.
🏷️ Miscellaneous
📂 Libraries for working with dependency injection.
⭐ 15 stars
Detailed Description of gontainer/gontainer
Gontainer
A Dependency Injection container for GO. Gontainer is concurrent-safe, supports scopes and offers hot swapping.
If the code generation is not for you, see how to manually build a container.
Using the bootstrapping technique, Gontainer uses itself to compile its dependencies.
Docs
- Documentation
- Interface
Installation
homebrew
brew install gontainer/homebrew-tap/gontainer
go install
go install github.com/gontainer/gontainer@latest
Manual compilation
git clone [email protected]:gontainer/gontainer.git
cd gontainer
GONTAINER_BINARY=/usr/local/bin/gontainer make
TL;DR
Describe dependencies
Either YAML or GO
YAML
File gontainer/gontainer.yaml
:
meta:
pkg: "gontainer"
constructor: "New"
imports:
mypkg: "github.com/user/repo/pkg"
parameters:
appPort: '%envInt("APP_PORT", 9090)%' # get the port from the ENV variable if it exists, otherwise, use the default one
services:
endpointHelloWorld:
constructor: "mypkg.NewHelloWorld"
serveMux:
constructor: '"net/http".NewServeMux' # serveMux := http.NewServerMux()
calls: #
- [ "Handle", [ "/hello-world", "@endpointHelloWorld" ] ] # serveMux.Handle("/hello-world", gontainer.Get("endpointHelloWorld"))
server:
getter: "GetServer" # func (*gontainer) GetServer() (*http.Server, error) { ... }
must_getter: true # func (*gontainer) MustGetServer() *http.Server { ... }
type: '*"net/http".Server' #
value: '&"net/http".Server{}' # server := &http.Server{}
fields: #
Addr: ":%appPort%" # server.Addr = ":" + gontainer.GetParam("appPort")
Handler: "@serveMux" # server.Handler = gontainer.Get("serverMux")
Compile it
gontainer build -i gontainer/gontainer.yaml -o gontainer/container.go
# it can read multiple configuration files, e.g.
# gontainer build -i gontainer/gontainer.yaml -i gontainer/dev/\*.yaml -o gontainer/container.go
GO
File gontainer/gontainer.go
:
package gontainer
import (
"net/http"
"os"
"github.com/gontainer/gontainer-helpers/v3/container"
"github.com/user/repo/pkg"
)
type gontainer struct {
*container.SuperContainer
}
func (g *gontainer) MustGetServer() *http.Server {
raw, err := g.Get("server")
if err != nil {
panic(err)
}
return raw.(*http.Server)
}
func New() *gontainer {
sc := &gontainer{
SuperContainer: container.NewSuperContainer(),
}
sc.OverrideParam("serverAddr", container.NewDependencyProvider(func() string {
if v, ok := os.LookupEnv("APP_PORT"); ok {
return ":" + v
}
return ":9090"
}))
endpointHelloWorld := container.NewService()
endpointHelloWorld.SetConstructor(pkg.NewHelloWorld)
sc.OverrideService("endpointHelloWorld", endpointHelloWorld)
serveMux := container.NewService()
serveMux.SetConstructor(http.NewServeMux)
serveMux.AppendCall(
"Handle",
container.NewDependencyValue("/hello-world"),
container.NewDependencyService("endpointHelloWorld"),
)
sc.OverrideService("serveMux", serveMux)
server := container.NewService()
server.SetConstructor(func() *http.Server {
return &http.Server{}
})
server.SetField("Addr", container.NewDependencyProvider(func() (interface{}, error) {
return sc.GetParam("serverAddr")
}))
server.SetField("Handler", container.NewDependencyService("serveMux"))
sc.OverrideService("server", server)
return sc
}
Voilà!
File main.go
:
package main
import (
"github.com/user/repo/gontainer"
)
func main() {
c := gontainer.New()
s := c.MustGetServer()
err := s.ListenAndServe()
if err != nil {
panic(err)
}
}