- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
142 lines
3.5 KiB
Go
142 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
_ "carrotskin/docs" // Swagger文档
|
|
"carrotskin/internal/container"
|
|
"carrotskin/internal/handler"
|
|
"carrotskin/internal/middleware"
|
|
"carrotskin/pkg/auth"
|
|
"carrotskin/pkg/config"
|
|
"carrotskin/pkg/database"
|
|
"carrotskin/pkg/email"
|
|
"carrotskin/pkg/logger"
|
|
"carrotskin/pkg/redis"
|
|
"carrotskin/pkg/storage"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func main() {
|
|
// 初始化配置
|
|
if err := config.Init(); err != nil {
|
|
log.Fatalf("配置加载失败: %v", err)
|
|
}
|
|
cfg := config.MustGetConfig()
|
|
|
|
// 初始化日志
|
|
if err := logger.Init(cfg.Log); err != nil {
|
|
log.Fatalf("日志初始化失败: %v", err)
|
|
}
|
|
loggerInstance := logger.MustGetLogger()
|
|
defer loggerInstance.Sync()
|
|
|
|
// 初始化数据库
|
|
if err := database.Init(cfg.Database, loggerInstance); err != nil {
|
|
loggerInstance.Fatal("数据库初始化失败", zap.Error(err))
|
|
}
|
|
defer database.Close()
|
|
|
|
// 执行数据库迁移
|
|
if err := database.AutoMigrate(loggerInstance); err != nil {
|
|
loggerInstance.Fatal("数据库迁移失败", zap.Error(err))
|
|
}
|
|
|
|
// 初始化种子数据
|
|
if err := database.Seed(loggerInstance); err != nil {
|
|
loggerInstance.Fatal("种子数据初始化失败", zap.Error(err))
|
|
}
|
|
|
|
// 初始化JWT服务
|
|
if err := auth.Init(cfg.JWT); err != nil {
|
|
loggerInstance.Fatal("JWT服务初始化失败", zap.Error(err))
|
|
}
|
|
|
|
// 初始化Redis
|
|
if err := redis.Init(cfg.Redis, loggerInstance); err != nil {
|
|
loggerInstance.Fatal("Redis连接失败", zap.Error(err))
|
|
}
|
|
defer redis.MustGetClient().Close()
|
|
|
|
// 初始化对象存储 (RustFS - S3兼容)
|
|
var storageClient *storage.StorageClient
|
|
if err := storage.Init(cfg.RustFS); err != nil {
|
|
loggerInstance.Warn("对象存储连接失败,某些功能可能不可用", zap.Error(err))
|
|
} else {
|
|
storageClient = storage.MustGetClient()
|
|
loggerInstance.Info("对象存储连接成功")
|
|
}
|
|
|
|
// 初始化邮件服务
|
|
if err := email.Init(cfg.Email, loggerInstance); err != nil {
|
|
loggerInstance.Fatal("邮件服务初始化失败", zap.Error(err))
|
|
}
|
|
emailServiceInstance := email.MustGetService()
|
|
|
|
// 创建依赖注入容器
|
|
c := container.NewContainer(
|
|
database.MustGetDB(),
|
|
redis.MustGetClient(),
|
|
loggerInstance,
|
|
auth.MustGetJWTService(),
|
|
storageClient,
|
|
emailServiceInstance,
|
|
)
|
|
|
|
// 设置Gin模式
|
|
if cfg.Server.Mode == "production" {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
}
|
|
|
|
// 创建路由
|
|
router := gin.New()
|
|
|
|
// 添加中间件
|
|
router.Use(middleware.Logger(loggerInstance))
|
|
router.Use(middleware.Recovery(loggerInstance))
|
|
router.Use(middleware.CORS())
|
|
|
|
// 使用依赖注入方式注册路由
|
|
handler.RegisterRoutesWithDI(router, c)
|
|
|
|
// 创建HTTP服务器
|
|
srv := &http.Server{
|
|
Addr: cfg.Server.Port,
|
|
Handler: router,
|
|
ReadTimeout: cfg.Server.ReadTimeout,
|
|
WriteTimeout: cfg.Server.WriteTimeout,
|
|
}
|
|
|
|
// 启动服务器
|
|
go func() {
|
|
loggerInstance.Info("服务器启动", zap.String("port", cfg.Server.Port))
|
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
loggerInstance.Fatal("服务器启动失败", zap.Error(err))
|
|
}
|
|
}()
|
|
|
|
// 等待中断信号优雅关闭
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
<-quit
|
|
loggerInstance.Info("正在关闭服务器...")
|
|
|
|
// 设置关闭超时
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
if err := srv.Shutdown(ctx); err != nil {
|
|
loggerInstance.Fatal("服务器强制关闭", zap.Error(err))
|
|
}
|
|
|
|
loggerInstance.Info("服务器已关闭")
|
|
}
|