调整项目架构,让框架更优化

This commit is contained in:
2026-07-20 21:39:01 +08:00
parent 987b16fd41
commit 121928733b
16 changed files with 866 additions and 689 deletions

View File

@@ -10,6 +10,7 @@ import (
"git.toowon.com/jimmy/go-common/config"
"git.toowon.com/jimmy/go-common/email"
"git.toowon.com/jimmy/go-common/excel"
commonhttp "git.toowon.com/jimmy/go-common/http"
"git.toowon.com/jimmy/go-common/i18n"
"git.toowon.com/jimmy/go-common/logger"
"git.toowon.com/jimmy/go-common/middleware"
@@ -38,7 +39,6 @@ type Factory struct {
db *gorm.DB
redis *redis.Client
i18n *i18n.I18n
excel *excel.Excel
chain *middleware.Chain
mu sync.Mutex
@@ -47,13 +47,6 @@ type Factory struct {
// Option Factory 可选项(支持重载模块实现)
type Option func(*Factory)
// WithStorage 注入自定义存储实现
func WithStorage(s storage.Storage) Option {
return func(f *Factory) {
f.storage = s
}
}
// Init 从配置文件初始化全局 Factory启动时调用一次
func Init(filePath string, opts ...Option) error {
cfg, err := config.LoadFromFile(filePath)
@@ -86,6 +79,15 @@ func (f *Factory) Config() *config.Config {
return f.cfg
}
// NewHandler 创建 HTTP 出参处理器,并自动注入已配置的 i18n若可用
// 能力仍在 *http.Handler 上Success / ErrorFactory 不透传出参方法。
func (f *Factory) NewHandler(w http.ResponseWriter, r *http.Request, opts ...commonhttp.HandlerOption) *commonhttp.Handler {
if i18nInst, err := f.getI18n(); err == nil && i18nInst != nil {
opts = append([]commonhttp.HandlerOption{commonhttp.WithI18n(i18nInst)}, opts...)
}
return commonhttp.NewHandler(w, r, opts...)
}
func (f *Factory) getLogger() (*logger.Logger, error) {
if f.logger != nil {
return f.logger, nil
@@ -107,7 +109,7 @@ func (f *Factory) getLogger() (*logger.Logger, error) {
return l, nil
}
// Logger 获取日志对象
// Logger 获取日志对象(无 logger 配置时使用默认配置)
func (f *Factory) Logger() (*logger.Logger, error) {
return f.getLogger()
}
@@ -312,21 +314,9 @@ func (f *Factory) I18n() (*i18n.I18n, error) {
return f.getI18n()
}
func (f *Factory) getExcel() *excel.Excel {
if f.excel != nil {
return f.excel
}
f.mu.Lock()
defer f.mu.Unlock()
if f.excel == nil {
f.excel = excel.NewExcel()
}
return f.excel
}
// Excel 获取 Excel 导出器
// Excel 创建 Excel 导出器(每次新建,避免共享可变文件状态)
func (f *Factory) Excel() *excel.Excel {
return f.getExcel()
return excel.NewExcel()
}
// MiddlewareChain 获取默认中间件链
@@ -341,8 +331,11 @@ func (f *Factory) MiddlewareChain() *middleware.Chain {
}
var mws []func(http.Handler) http.Handler
l, _ := f.getLogger()
i18nInst, _ := f.getI18n()
// logger 无配置时有默认实现;失败则降级为 nilRecovery/Logging 可处理)
l, _ := f.getLoggerUnlocked()
// i18n 为可选:未配置时 Recovery 使用默认文案
i18nInst, _ := f.getI18nUnlocked()
mws = append(mws, middleware.Recovery(&middleware.RecoveryConfig{
Logger: l,
@@ -384,6 +377,41 @@ func (f *Factory) MiddlewareChain() *middleware.Chain {
return f.chain
}
// getLoggerUnlocked 在已持有 f.mu 时初始化 logger供 MiddlewareChain 使用)
func (f *Factory) getLoggerUnlocked() (*logger.Logger, error) {
if f.logger != nil {
return f.logger, nil
}
var cfg *config.LoggerConfig
if f.cfg != nil {
cfg = f.cfg.Logger
}
l, err := logger.NewLogger(cfg)
if err != nil {
return nil, err
}
f.logger = l
return l, nil
}
// getI18nUnlocked 在已持有 f.mu 时初始化 i18n供 MiddlewareChain 使用)
func (f *Factory) getI18nUnlocked() (*i18n.I18n, error) {
if f.i18n != nil {
return f.i18n, nil
}
if f.cfg == nil || f.cfg.I18n == nil {
return nil, fmt.Errorf("i18n config is nil")
}
i := i18n.NewI18n(f.cfg.I18n.DefaultLang)
if f.cfg.I18n.LocalesDir != "" {
if err := i.LoadFromDir(f.cfg.I18n.LocalesDir); err != nil {
return nil, err
}
}
f.i18n = i
return i, nil
}
// Migrator 创建迁移器并加载指定目录下的 SQL 文件
func (f *Factory) Migrator(migrationsDir string) (*migration.Migrator, error) {
db, err := f.getDatabase()