package main import ( "fmt" "log" "os" "os/signal" "syscall" "context" "net/http" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" "photography-backend/internal/config" "photography-backend/internal/repository/postgres" "photography-backend/internal/service/auth" "photography-backend/internal/api/handlers" "photography-backend/internal/api/middleware" "photography-backend/internal/api/routes" "photography-backend/pkg/logger" ) func main() { // 加载配置 cfg, err := config.LoadConfig("configs/config.yaml") if err != nil { log.Fatalf("Failed to load config: %v", err) } // 初始化日志 zapLogger, err := logger.InitLogger(&cfg.Logger) if err != nil { log.Fatalf("Failed to initialize logger: %v", err) } defer zapLogger.Sync() // 初始化数据库 db, err := postgres.NewDatabase(&cfg.Database) if err != nil { zapLogger.Fatal("Failed to connect to database", zap.Error(err)) } defer db.Close() // 自动迁移数据库 if err := db.AutoMigrate(); err != nil { zapLogger.Fatal("Failed to migrate database", zap.Error(err)) } // 初始化仓库 userRepo := postgres.NewUserRepository(db.DB) photoRepo := postgres.NewPhotoRepository(db.DB) categoryRepo := postgres.NewCategoryRepository(db.DB) tagRepo := postgres.NewTagRepository(db.DB) // 初始化服务 jwtService := auth.NewJWTService(&cfg.JWT) authService := auth.NewAuthService(userRepo, jwtService) // 初始化处理器 authHandler := handlers.NewAuthHandler(authService) // 初始化中间件 authMiddleware := middleware.NewAuthMiddleware(jwtService) // 设置Gin模式 if cfg.IsProduction() { gin.SetMode(gin.ReleaseMode) } // 创建Gin引擎 r := gin.New() // 添加中间件 r.Use(middleware.RequestIDMiddleware()) r.Use(middleware.LoggerMiddleware(zapLogger)) r.Use(middleware.CORSMiddleware(&cfg.CORS)) r.Use(gin.Recovery()) // 健康检查 r.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "ok", "timestamp": time.Now().Unix(), "version": cfg.App.Version, }) }) // 设置路由 routes.SetupRoutes(r, &routes.Handlers{ Auth: authHandler, }, authMiddleware) // 创建HTTP服务器 server := &http.Server{ Addr: cfg.GetServerAddr(), Handler: r, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } // 启动服务器 go func() { zapLogger.Info("Starting server", zap.String("addr", server.Addr)) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { zapLogger.Fatal("Failed to start server", zap.Error(err)) } }() // 等待中断信号 quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit zapLogger.Info("Shutting down server...") // 优雅关闭 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { zapLogger.Fatal("Server forced to shutdown", zap.Error(err)) } zapLogger.Info("Server exited") }