前言
多年前曾经梦想着能有一天能在 Go 语言中使用上 Spring 那样强大的框架,幸运的是我找到了go-spring,一款类似 Spring 的库,我很喜欢它,并且在我的项目中深度使用它,它给我带来了非常酷的编程体验。
然而很不幸的是最近 go-spring 停止更新了(最近的一次提交停留在九个月之前),一些问题无法得到有效的解决,因此我决定创建一个基于 go-spring 的开源库,我为它修复了一系列 bug ,并添加了一些新得特性,并对代码结构进行了简化,将外部生态从核心库中移除,仅保留核心功能,外部生态预计将来将作为独立的仓库存在,我将持续继续将它维护下去,也希望有感兴趣的人可以一起参与进来一起持续开发它。
仓库地址: https://github.com/go-spring-projects/go-spring
特性
- IoC 容器: 实现了基于反射的控制反转(IoC)容器,支持结构体、函数和常量的注入。这意味着你可以使用' autowired '标签来自动注入依赖,而不必手动管理它们。
- 配置管理: 受 Spring 的 @Value 注释的启发,Go-Spring 允许您从多个源(如环境变量、文件、命令行参数等)获取配置项。这为配置管理带来了前所未有的灵活性。
- 配置验证器: 通过支持自定义验证器扩展扩展了其健壮的配置管理功能。这使您能够对属性执行有效性检查,确保仅将有效的配置应用于您的应用程序。
- 结构化日志: 使用标准库 slog 提供内置日志记录器支持,以实现有效和简化的日志记录。这种增强提供了清晰、简洁和结构良好的日志信息,有助于系统调试和性能监视。
- 动态属性: 提供动态属性刷新功能,让您无需重新启动应用程序即可动态更新应用程序属性。它满足了需要高可用性和实时响应的应用程序的需求。
- 依赖序事件: 按照 bean 依赖关系的顺序,确保根据对象的生命周期正确通知初始化和销毁事件。这增强了系统在其生命周期运行中的鲁棒性和可靠性。
动态属性例子
允许在运行时动态刷新属性,不仅支持基本数据类型,还支持结构、切片和 Map 类型。
package main
import (
"fmt"
"log/slog"
"net/http"
"github.com/go-spring-projects/go-spring/dync"
"github.com/go-spring-projects/go-spring/gs"
)
type Handler struct {
Open dync.Bool `value:"${server.open:=true}"`
}
func (h *Handler) OnInit(ctx gs.Context) error {
http.HandleFunc("/server/status", func(writer http.ResponseWriter, request *http.Request) {
if !h.Open.Value() {
http.Error(writer, "server closed", http.StatusNotAcceptable)
return
}
fmt.Fprint(writer, "server running")
})
return nil
}
type Server struct {
Logger *slog.Logger `logger:""`
}
func (s *Server) OnInit(ctx gs.Context) error {
props := ctx.(gs.Container).Properties()
http.HandleFunc("/server/status/open", func(writer http.ResponseWriter, request *http.Request) {
props.Set("server.open", "true")
s.Logger.Info("server opened")
})
http.HandleFunc("/server/status/close", func(writer http.ResponseWriter, request *http.Request) {
props.Set("server.open", "false")
s.Logger.Info("server closed")
})
go func() {
http.ListenAndServe(":7878", nil)
}()
return nil
}
func main() {
gs.Object(new(Handler))
gs.Object(new(Server))
if err := gs.Run(); nil != err {
panic(err)
}
}
// Output:
//
// $ curl http://127.0.0.1:7878/server/status
// server running
//
// $ curl http://127.0.0.1:7878/server/status/close
//
// $ curl http://127.0.0.1:7878/server/status
// server closed
//
// $ curl http://127.0.0.1:7878/server/status/open
//
// $ curl http://127.0.0.1:7878/server/status
// server running
参数校验器例子
Go-Spring允许您注册自定义值验证器。如果值验证失败,则Go-Spring将在启动阶段报告一个错误。
在这例子中, 我们将使用 go-validator/validator, 您可以参考这个示例来注册您的自定义验证器。
package main
import (
"fmt"
"log/slog"
"github.com/go-spring-projects/go-spring/conf"
"github.com/go-spring-projects/go-spring/gs"
"gopkg.in/validator.v2"
)
const validatorTagName = "validate"
type validatorWrapper struct {
validator *validator.Validator
}
func (v *validatorWrapper) Field(tag string, i interface{}) error {
if 0 == len(tag) {
return nil
}
return v.validator.Valid(i, tag)
}
func init() {
conf.Register(validatorTagName, &validatorWrapper{validator: validator.NewValidator().WithTag(validatorTagName)})
}
//--------------------------------------------------------------------------
type DBOptions struct {
UserName string `value:"${username}"`
Password string `value:"${password}"`
IP string `value:"${ip}"`
Port int32 `value:"${port}" validate:"min=1024,max=65535"`
DB string `value:"${db}" validate:"nonzero"`
}
type MysqlDatabase struct {
Logger *slog.Logger `logger:""`
Options DBOptions `value:"${db}"`
}
func (md *MysqlDatabase) OnInit(ctx gs.Context) error {
md.Logger.Info("mysql connection summary",
"url", fmt.Sprintf("mysql://%s:%s@%s:%d/%s", md.Options.UserName, md.Options.Password, md.Options.IP, md.Options.Port, md.Options.DB))
return nil
}
func main() {
gs.Property("db.username", "admin")
gs.Property("db.password", "123456")
gs.Property("db.ip", "127.0.0.1")
gs.Property("db.port", "0") // set db.port=0
gs.Property("db.db", "test")
gs.Object(new(MysqlDatabase))
if err := gs.Run(); nil != err {
panic(err)
}
}
//
// Output:
// panic: container refresh failed
// ↳object bean "main/main.MysqlDatabase:MysqlDatabase" /projects/go-project/gocase/validator/main.go:58
// ↳bind MysqlDatabase.Options error: validate MysqlDatabase.Options.Port error: less than min
更多特性请参考说明: go-spring-projects/go-spring
最后还要感谢原作者lvan100的辛勤付出。