很高興宣布 Go-Spring 全新版本正式發布!這是一個融合了 Java Spring 生態成熟理念 與 Go 語言高性能特性 ? 的現代框架, 旨在為 Go 開發者 ?? 提供更高效、更優雅的應用開發體驗 ?。
框架簡介
Go-Spring 是一個面向現代 Go 應用開發的高性能框架,靈感源自 Java 社區的 Spring / Spring Boot。它的設計理念深度融合 Go 語言的特性,既保留了 Spring 世界中成熟的開發范式,如依賴注入(DI)、自動配置和生命周期管理, 又避免了傳統框架可能帶來的繁復和性能開銷。 Go-Spring 讓開發者能夠在保持 Go 原生風格與執行效率的前提下,享受更高層次的抽象與自動化能力。
無論你是在開發單體應用,還是構建基于微服務的分布式系統,Go-Spring 都提供了統一且靈活的開發體驗。它以“開箱即用”的方式簡化了項目搭建流程,減少模板代碼的編寫需求,并且不強加侵入式的框架結構,讓開發者可以更專注于業務邏輯的實現。 Go-Spring 致力于提升開發效率、可維護性和系統的一致性,是 Go 語言生態中一個具有里程碑意義的框架。
特性一覽
Go-Spring 提供了豐富而實用的特性,幫助開發者高效構建現代 Go 應用:
?極致啟動性能
基于 Go 的
init()
機制進行 Bean 注冊,無運行時掃描,啟動迅速;注入僅依賴初始化階段的反射,運行時零反射,保障性能最大化。
開箱即用、無侵入式設計
支持結構體標簽注入與鏈式配置,無需掌握復雜概念即可使用;
不強依賴接口或繼承結構,業務邏輯保持原生 Go 風格。
配置熱更新,實時生效
多格式、多來源配置加載,支持環境隔離與動態刷新;
配置變更可即時應用,便于灰度發布與在線調參。
??靈活依賴注入機制
支持構造函數注入、結構體字段注入、構造函數參數注入多種方式;
注入行為可按配置項或運行環境靈活調整。
多模型服務啟動支持
內建 HTTP Server 啟動器,快速部署 Web 服務;
支持
Runner
、Job
、Server
三類運行模型,適配不同服務形態;生命周期鉤子完備,支持優雅啟停。
內建測試能力
與
go test
無縫集成,支持 Bean Mock 和依賴注入,輕松編寫單元測試。
Go-Spring 使用 Go Modules 管理依賴,安裝非常簡單:
go get github.com/go-spring/spring-core
快速開始
Go-Spring 主打“開箱即用”,下面通過兩個示例,快速感受其強大能力。
更多示例請見:gs/examples示例一:最小 API 服務
func main() {
http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world!"))
})
gs.Run()
}
訪問方式:
curl http://127.0.0.1:9090/echo
# 輸出: hello world!
? 無需繁雜配置,Go 標準庫http
可以直接使用;
?gs.Run()
接管生命周期,支持優雅退出、信號監聽等能力。
示例二:基礎特性展示
func init() {
gs.Object(&Service{})
gs.Provide(func (s *Service) *http.ServeMux {
http.HandleFunc("/echo", s.Echo)
http.HandleFunc("/refresh", s.Refresh)
return http.DefaultServeMux
})
sysconf.Set("start-time", time.Now().Format(timeLayout))
sysconf.Set("refresh-time", time.Now().Format(timeLayout))
}
const timeLayout = "2006-01-02 15:04:05.999 -0700 MST"
type Service struct {
StartTime time.Time `value:"${start-time}"`
RefreshTime gs.Dync[time.Time] `value:"${refresh-time}"`
}
func (s *Service) Echo(w http.ResponseWriter, r *http.Request) {
str := fmt.Sprintf("start-time: %s refresh-time: %s",
s.StartTime.Format(timeLayout),
s.RefreshTime.Value().Format(timeLayout))
w.Write([]byte(str))
}
func (s *Service) Refresh(w http.ResponseWriter, r *http.Request) {
sysconf.Set("refresh-time", time.Now().Format(timeLayout))
gs.RefreshProperties()
w.Write([]byte("OK!"))
}
訪問方式:
curl http://127.0.0.1:9090/echo # 查看當前時間
curl http://127.0.0.1:9090/refresh # 觸發熱刷新
?value
標簽自動綁定配置;
?gs.Dync[T]
實現字段熱更新;
?gs.Object
gs.Provide()
注冊 Bean。
配置管理
Go-Spring 提供了靈活強大的配置加載機制,支持從多種來源獲取配置項,輕松滿足多環境、多部署場景的需求。 無論是本地開發、容器化部署,還是云原生架構,Go-Spring 都能夠提供一致而靈活的配置支持。
為了應對配置項來源多樣、覆蓋關系復雜的實際需求,Go-Spring 構建了一套分層配置加載體系。 系統會在啟動時自動合并不同來源的配置項,并按照優先級規則進行解析和覆蓋。
配置優先級
命令行參數
使用-Dkey=value
格式注入,優先級最高,適合快速覆蓋運行時配置。環境變量
直接讀取操作系統環境變量,方便在容器或 CI/CD 流水線中注入配置。遠程文件
支持從配置中心拉取配置,具備定時拉取與熱更新能力,適用于集中式配置管理。本地文件
支持常見格式,如.yaml
、.properties
、.toml
,適合大多數開發與部署場景。內存配置 (
sysconf
)
適用于測試場景或運行時臨時注入配置,具備較高的靈活性。結構體默認值
通過結構體標簽設定默認值,是配置體系中的最后兜底機制。
示例:屬性綁定
type AppConfig struct {
Name string `value:"${app.name}"`
Version string `value:"${app.version}"`
}
Bean 管理
在 Go-Spring 中,Bean 是應用的核心構建單元,類似于其他依賴注入框架中的組件概念。 整個系統圍繞 Bean 的注冊、初始化、依賴注入與生命周期管理進行組織。 Go-Spring 不依賴運行時反射,而是通過編譯期生成元數據和顯式調用方式,實現了類型安全、性能優越的 Bean 管理機制。 這樣設計特別適合構建高性能、可維護性強的大型系統。
框架采用“顯式注冊 + 標簽聲明 + 條件裝配”的組合方式,讓開發者對 Bean 的注冊與依賴關系有清晰的控制。 由于不依賴運行時容器掃描,也沒有魔法配置,這種做法在保證開發體驗的同時, 進一步提升了調試和運維的可控性,實現了零侵入、(運行時)零反射的目標。
1?? 注冊方式
Go-Spring 提供多種方式注冊 Bean:
gs.Object(obj)
- 將已有對象注冊為 Beangs.Provide(ctor, args...)
- 使用構造函數生成并注冊 Beangs.Register(bd)
- 注冊完整 Bean 定義(適合底層封裝或高級用法)gs.GroupRegister(fn)
- 批量注冊多個 Bean(常用于模塊初始化等場景)
示例:
gs.Object(&Service{}) // 注冊結構體實例
gs.Provide(NewService) // 使用構造函數注冊
gs.Provide(NewRepo, gs.ValueArg("db")) // 構造函數帶參數
gs.Register(gs.NewBean(NewService)) // 完整定義注冊
// 批量注冊多個 Bean
gs.GroupRegister(func (p conf.Properties) []*gs.BeanDefinition {
return []*gs.BeanDefinition{
gs.NewBean(NewUserService),
gs.NewBean(NewOrderService),
}
})
2?? 注入方式
Go-Spring 提供了多種靈活的依賴注入方式。
1. 結構體字段注入
通過標簽將配置項或 Bean 注入結構體字段,適合絕大多數場景。
type App struct {
Logger *log.Logger `autowire:""`
Filters []*Filter `autowire:"access,*?"`
StartTime time.Time `value:"${start-time}"`
}
value:"${...}"
表示綁定配置值;autowire:""
表示按類型和名稱自動注入;autowire:"access,*?"
表示按類型和名稱注入多個 Bean。
通過函數參數完成自動注入,Go-Spring 會自動推斷并匹配依賴 Bean。
func NewService(logger *log.Logger) *Service {
return &Service{Logger: logger}
}
gs.Provide(NewService)
3. 構造函數參數注入
可通過參數包裝器明確注入行為,更適用于復雜構造邏輯:
gs.Provide(NewService,
TagArg("${log.level}"), // 從配置注入
ValueArg("value"), // 直接值注入
BindArg(parseFunc), // option 函數注入
)
可用的參數類型:
TagArg(tag)
:從配置中提取值ValueArg(value)
:使用固定值IndexArg(i, arg)
:按參數位置注入BindArg(fn, args...)
:通過 option 函數注入
開發者可以為每個 Bean 顯式聲明初始化、銷毀、依賴、條件注冊等行為。
gs.Provide(NewService).
Name("myService").
Init(func(s *Service) { ... }).
Destroy(func(s *Service) { ... }).
Condition(OnProperty("feature.enabled")).
DependsOn(gs.BeanSelectorFor[*Repo]()).
Export(gs.As[ServiceInterface]()).
AsRunner()
配置項說明:
Name(string)
:指定 Bean 名稱Init(fn)
:初始化函數(支持方法名字符串)Destroy(fn)
:銷毀函數(支持方法名字符串)DependsOn(...)
:指定依賴的其他 BeanCondition(...)
:條件注冊控制Export(...)
:將 Bean 作為接口導出,支持多接口導出
Go-Spring 借鑒 Spring 的@Conditional
思想,實現了靈活強大的條件注入系統。通過配置、環境、上下文等條件動態決定 Bean 是否注冊,實現“按需裝配”。 這在多環境部署、插件化架構、功能開關、灰度發布等場景中尤為關鍵。
常用條件類型
OnProperty("key")
:當指定配置 key 存在時激活OnMissingProperty("key")
:當指定配置 key 不存在時激活OnBean[Type]("name")
:當指定類型/名稱的 Bean 存在時激活OnMissingBean[Type]("name")
:當指定類型/名稱的 Bean 不存在時激活OnSingleBean[Type]("name")
:當指定類型/名稱的 Bean 是唯一實例時激活OnFunc(func(ctx CondContext) bool)
:使用自定義條件邏輯判斷是否激活
示例:
gs.Provide(NewService).
Condition(OnProperty("service.enabled"))
只有當配置文件中存在service.enabled=true
時,NewService
才會注冊。
支持組合條件
Go-Spring 支持組合多個條件,構建更復雜的判斷邏輯:
Not(...)
- 對條件取反And(...)
- 所有條件都滿足時成立Or(...)
- 任一條件滿足即成立None(...)
- 所有條件都不滿足時成立
示例:
gs.Provide(NewService).
Condition(
And(
OnProperty("feature.enabled"),
Not(OnBean[*DeprecatedService]()),
),
)
該 Bean 會在feature.enabled
開啟且未注冊*DeprecatedService
時啟用。
動態配置
Go-Spring 支持輕量級的配置熱更新機制。通過泛型類型gs.Dync[T]
和gs.RefreshProperties()
, 應用可以在運行中實時感知配置變更,而無需重啟。這對于微服務架構中的灰度發布、動態調參、配置中心集成等場景尤為關鍵。
使用方式
使用
gs.Dync[T]
聲明動態字段
通過泛型類型gs.Dync[T]
包裝字段,即可監聽配置變化并自動更新:
type Config struct {
Version gs.Dync[string] `value:"${app.version}"`
}
調用時通過 .Value() 獲取當前值,框架在配置變更時會自動更新該值。
調用
gs.RefreshProperties()
觸發刷新
在配置發生變化后,調用此方法可以讓所有動態字段立即更新:
gs.RefreshProperties()
示例:版本號更新
const versionKey = "app.version"
type App struct {
Version gs.Dync[string] `value:"${app.version:=v0.0.1}"`
}
func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Version:", a.Version.Value())
}
func RefreshVersion(w http.ResponseWriter, r *http.Request) {
sysconf.Set(versionKey, "v2.0.1")
gs.RefreshProperties()
fmt.Fprintln(w, "Version updated!")
}
func main() {
gs.Object(&App{})
gs.Provide(func(app *App) *http.ServeMux {
http.Handle("/", app)
http.HandleFunc("/refresh", RefreshVersion)
return http.DefaultServeMux
})
gs.Run()
}
運行程序后,訪問/
會輸出當前版本,訪問/refresh
后,再次訪問/
即可看到更新后的版本號。
? 自定義 Server
Go-Spring 提供了通用的Server
接口,用于注冊各種服務組件(如 HTTP、gRPC、WebSocket 等)。所有注冊的 Server 都會自動接入應用的生命周期管理,支持并發啟動、統一關閉等能力,幫助開發者構建結構整潔、管理一致的系統。
Server 接口定義
type Server interface {
ListenAndServe(sig ReadySignal) error
Shutdown(ctx context.Context) error
}
ListenAndServe(sig ReadySignal)
: 啟動服務,并在收到sig
信號后對外提供服務。Shutdown(ctx)
: 優雅關閉服務,釋放資源。
type ReadySignal interface {
TriggerAndWait() <-chan struct{}
}
你可以在ListenAndServe
中等到主流程觸發啟動完成信號,然后正式對外提供服務。
示例:HTTP Server 接入
func init() {
gs.Object(NewServer()).AsServer()
}
type MyServer struct {
svr *http.Server
}
func NewServer() *MyServer {
return &MyServer{
svr: &http.Server{Addr: ":8080"},
}
}
func (s *MyServer) ListenAndServe(sig gs.ReadySignal) error {
ln, err := net.Listen("tcp", s.svr.Addr)
if err != nil {
return err
}
<-sig.TriggerAndWait() // 等待啟動信號
return s.svr.Serve(ln)
}
func (s *MyServer) Shutdown(ctx context.Context) error {
return s.svr.Shutdown(ctx)
}
示例:gRPC Server 接入
type GRPCServer struct {
svr *grpc.Server
}
// ...
func (s *GRPCServer) ListenAndServe(sig gs.ReadySignal) error {
lis, err := net.Listen("tcp", ":9595")
if err != nil {
return err
}
<-sig.TriggerAndWait()
return s.svr.Serve(lis)
}
func (s *GRPCServer) Shutdown(ctx context.Context) error {
s.svr.GracefulStop()
return nil
}
多 Server 并發運行
所有通過.AsServer()
注冊的服務,會在gs.Run()
時并發啟動,并統一監聽退出信號:
gs.Object(&HTTPServer{}).AsServer()
gs.Object(&GRPCServer{}).AsServer()
? 應用生命周期管理
Go-Spring 將應用運行周期抽象為三個角色:Runner
、Job
、Server
,含義分別如下:
Runner:應用啟動后立即執行的一次性任務(初始化等)
Job:應用運行期間持續運行的后臺任務(守護線程、輪詢等)
Server:對外提供服務的長期服務進程(如 HTTP/gRPC 等)
這些角色可以通過.AsRunner() / .AsJob() / .AsServer()
進行注冊。
示例:Runner
type Bootstrap struct{}
func (b *Bootstrap) Run() error {
fmt.Println("Bootstrap init...")
return nil
}
func init() {
gs.Object(&Bootstrap{}).AsRunner()
}
Runner 執行過程中如果返回錯誤,將會終止應用啟動流程。
示例:Job
type Job struct{}
func (j *Job) Run(ctx context.Context) error {
for {
select {
case <-ctx.Done():
fmt.Println("job exit")
return nil
default:
if gs.Exiting() {
return nil
}
time.Sleep(300 * time.Millisecond)
fmt.Println("job tick")
}
}
}
func init() {
gs.Object(&Job{}).AsJob()
}
Job 會在
gs.Run()
后啟動,直到退出信號到來;支持優雅停止,及時響應
ctx.Done()
或gs.Exiting()
狀態。
Go-Spring 提供了與標準go test
無縫集成的單元測試框架,讓依賴注入和模擬測試變得簡單高效。
1. 模擬對象注入
使用gstest.MockFor[T]().With(obj)
可以在運行時輕松替換任何 bean:
gstest.MockFor[*book_dao.BookDao]().With(&book_dao.BookDao{
Store: map[string]book_dao.Book{
"978-0132350884": {
Title: "Clean Code",
Author: "Robert C. Martin",
ISBN: "978-0132350884",
Publisher: "Prentice Hall",
},
},
})
2. 獲取測試對象
有兩種方式獲取被測試對象:
直接獲取實例:
o := gstest.Get[*BookDao](t)
assert.NotNil(t, o)
結構化注入:
s := gstest.Wire(t, new(struct {
SvrAddr string `value:"${server.addr}"`
Service *BookService `autowire:""`
BookDao *book_dao.BookDao `autowire:""`
}))
assert.That(t, s.SvrAddr).Equal("0.0.0.0:9090")
與其他框架的對比
Go-Spring 具備以下幾個顯著優勢:
功能點
Go-Spring
Wire
fx
dig
運行時 IoC 容器
編譯期校驗
部分支持
條件 Bean 支持
動態配置能力
生命周期管理
屬性綁定
零結構體侵入(無需修改原結構體)
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.