golang基于YAML的依赖注入容器插件库gontainer的使用
Golang基于YAML的依赖注入容器插件库gontainer的使用
Gontainer是一个用于Go语言的依赖注入容器,它支持并发安全、作用域和热交换功能。
安装
可以通过以下方式安装gontainer:
homebrew
brew install gontainer/homebrew-tap/gontainer
go install
go install github.com/gontainer/gontainer@latest
手动编译
git clone git@github.com:gontainer/gontainer.git
cd gontainer
GONTAINER_BINARY=/usr/local/bin/gontainer make
使用示例
YAML配置方式
创建gontainer/gontainer.yaml
文件:
meta:
pkg: "gontainer"
constructor: "New"
imports:
mypkg: "github.com/user/repo/pkg"
parameters:
appPort: '%envInt("APP_PORT", 9090)%' # 从环境变量获取端口,否则使用默认值9090
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")
然后编译它:
gontainer build -i gontainer/gontainer.yaml -o gontainer/container.go
Go代码方式
创建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
}
使用容器
创建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)
}
}
特性
- 并发安全
- 支持作用域
- 支持热交换
- 可以通过YAML或Go代码配置
- 自动生成容器代码
Gontainer使用自举技术,使用自身来编译其依赖项,这使得它非常灵活和强大。
更多关于golang基于YAML的依赖注入容器插件库gontainer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于YAML的依赖注入容器插件库gontainer的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang基于YAML的依赖注入容器插件库gontainer使用指南
gontainer是一个轻量级的Go语言依赖注入容器,支持通过YAML配置文件定义依赖关系。下面我将详细介绍如何使用gontainer。
安装
go get github.com/gontainer/gontainer
基本使用
1. 定义YAML配置文件
创建一个container.yml
文件:
parameters:
db.host: "localhost"
db.port: 3306
db.user: "root"
db.pass: "password"
services:
db.connection:
constructor: "database/sql.Open"
args:
- "mysql"
- "%db.user%:%db.pass%@tcp(%db.host%:%db.port%)/mydb"
calls:
- method: "SetMaxOpenConns"
args: [10]
- method: "SetMaxIdleConns"
args: [5]
user.repository:
constructor: "app/repository.NewUserRepository"
args: ["@db.connection"]
user.service:
constructor: "app/service.NewUserService"
args: ["@user.repository"]
2. 初始化容器
package main
import (
"github.com/gontainer/gontainer"
)
func main() {
// 创建容器
container := gontainer.NewContainer()
// 从YAML文件加载配置
err := container.LoadFromYAML("container.yml")
if err != nil {
panic(err)
}
// 获取服务
userService, err := container.Get("user.service")
if err != nil {
panic(err)
}
// 使用服务
// userService.(*service.UserService).SomeMethod()
}
高级特性
1. 参数注入
parameters:
app.debug: true
app.timeout: 30
services:
logger:
constructor: "app/logger.NewLogger"
args: ["%app.debug%"]
http.client:
constructor: "net/http.NewClient"
args: ["%app.timeout%"]
2. 方法调用
services:
cache.redis:
constructor: "github.com/go-redis/redis.NewClient"
args:
- addr: "localhost:6379"
calls:
- method: "Ping"
- method: "Set"
args: ["key", "value"]
3. 工厂方法
services:
random.generator:
factory: "math/rand.New"
args: ["@random.source"]
random.source:
constructor: "math/rand.NewSource"
args: [12345]
4. 标签支持
services:
payment.processor:
tags: ["payment", "processor"]
email.sender:
tags: ["notification"]
获取带标签的服务:
processors := container.GetByTag("payment")
实际示例
完整的Web应用示例
# container.yml
parameters:
app.env: "dev"
db.dsn: "user:pass@tcp(localhost:3306)/dbname?parseTime=true"
services:
db:
constructor: "database/sql.Open"
args: ["mysql", "%db.dsn%"]
calls:
- method: "SetMaxOpenConns"
args: [10]
user.repository:
constructor: "app/repositories.NewUserRepository"
args: ["@db"]
auth.service:
constructor: "app/services.NewAuthService"
args: ["@user.repository"]
http.server:
constructor: "app/http.NewServer"
args: ["@auth.service", "%app.env%"]
对应的Go代码:
package main
import (
"github.com/gontainer/gontainer"
"log"
)
func main() {
container := gontainer.NewContainer()
if err := container.LoadFromYAML("container.yml"); err != nil {
log.Fatal(err)
}
server, err := container.Get("http.server")
if err != nil {
log.Fatal(err)
}
// 启动服务器
// server.(*http.Server).Start()
}
最佳实践
-
分层配置:将不同环境的配置分开,如
container.dev.yml
、container.prod.yml
-
模块化:将大型应用的配置拆分为多个文件
-
参数化:将所有可变部分提取为参数
-
合理使用标签:通过标签组织相关服务
-
错误处理:始终检查容器操作的错误
总结
gontainer提供了一种简洁的方式来管理Go应用中的依赖关系,通过YAML配置文件可以清晰地表达服务间的依赖关系。它的主要优点包括:
- 配置与代码分离
- 支持多种依赖注入方式
- 轻量级且易于集成
- 支持参数化和标签
对于中小型Go项目,gontainer是一个不错的依赖注入解决方案,能够有效降低组件间的耦合度,提高代码的可测试性和可维护性。