// @title GoFaster API // @version 1.0 // @description GoFaster项目API文档 // @termsOfService http://swagger.io/terms/ // @contact.name API支持 // @contact.url http://www.gofaster.com/support // @contact.email support@gofaster.com // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host localhost:8080 // @BasePath /api // @schemes http // @securityDefinitions.apikey BearerAuth // @in header // @name Authorization // @description 请输入 "Bearer " + JWT token,例如: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." package main import ( "fmt" "gofaster/internal/auth" "gofaster/internal/core" "gofaster/internal/shared/config" "gofaster/internal/shared/database" "gofaster/internal/shared/logger" "gofaster/internal/shared/middleware" "net/http" "time" // 导入各模块 _ "gofaster/internal/auth" "gofaster/internal/auth/migration" _ "gofaster/internal/workflow" "github.com/gin-gonic/gin" ginSwagger "github.com/swaggo/gin-swagger" "go.uber.org/zap" _ "gofaster/docs" swaggerFiles "github.com/swaggo/files" ) func main() { printBanner() loc, err := time.LoadLocation("Asia/Shanghai") if err != nil { fmt.Printf("时区加载失败: %v\n", err) } else { fmt.Printf("时区加载成功: %v\n", loc) } // 列出可用时区(部分) fmt.Println("当前时间:", time.Now()) fmt.Println("UTC时间:", time.Now().UTC()) // 初始化配置 cfg, err := config.LoadConfig() if err != nil { panic(fmt.Sprintf("配置加载错误: %v\n", err)) } // 初始化日志 log := logger.NewLogger(cfg.Log.Level, cfg.Log.Path) defer log.Sync() // 初始化数据库 db, err := database.NewDB(&cfg.DB) if err != nil { log.Fatal("Failed to connect database", zap.Error(err)) } // 运行数据库迁移 if err := migration.RunMigrations(db); err != nil { log.Fatal("Failed to run database migrations", zap.Error(err)) } fmt.Printf("✅ 数据库迁移完成\n") // 初始化Redis redisClient := database.NewRedisClient(&cfg.Redis, log) defer redisClient.Close() // 创建模块管理器 moduleManager := core.NewModuleManager(log) // 自动发现并注册模块 if err := core.DiscoverModules(moduleManager); err != nil { log.Fatal("Failed to discover modules", zap.Error(err)) } fmt.Printf("✅ 模块发现完成\n") // 初始化所有模块 if err := moduleManager.InitModules(cfg, db, redisClient); err != nil { log.Fatal("Failed to initialize modules", zap.Error(err)) } fmt.Printf("✅ 模块初始化完成\n") // 创建Gin应用 app := gin.New() app.Use( middleware.Logger(log), middleware.RecoveryMiddleware(log), middleware.CORSMiddleware(), ) // 注册路由 api := app.Group("/api") moduleManager.RegisterRoutes(api) fmt.Printf("✅ 路由注册完成\n") // 路由同步(在路由注册完成后执行) if err := syncRoutesOnStartup(app, log, moduleManager); err != nil { log.Error("路由同步失败", zap.Error(err)) } else { fmt.Printf("✅ 路由同步完成\n") } // 健康检查端点 app.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{ "status": "ok", "message": "GoFaster API is running", "timestamp": "2024-01-01T00:00:00Z", }) }) // Swagger路由配置 app.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("http://localhost:8080/swagger/doc.json"), ginSwagger.DefaultModelsExpandDepth(-1), )) app.GET("/docs", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "/swagger/index.html") }) app.GET("/api-docs", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "/swagger/index.html") }) // 自定义Swagger UI页面 app.GET("/swagger-ui", func(c *gin.Context) { c.File("./swagger-ui.html") }) // 修复版本的Swagger UI页面(确保Authorize按钮显示) app.GET("/swagger-ui-fixed", func(c *gin.Context) { c.File("./swagger-ui-fixed.html") }) // 启动服务器 log.Info("Starting server", zap.String("port", cfg.Server.Port)) if err := app.Run(":" + cfg.Server.Port); err != nil { log.Fatal("Failed to start server", zap.Error(err)) } // 清理模块资源 // moduleManager.Cleanup() // 暂时注释掉,因为ModuleManager没有这个方法 } // syncRoutesOnStartup 应用启动时同步路由 func syncRoutesOnStartup(app *gin.Engine, log *zap.Logger, moduleManager *core.ModuleManager) error { // 通过模块管理器获取auth模块并执行路由同步 authModule, exists := moduleManager.GetModule("auth") if !exists { log.Error("auth模块不存在") return fmt.Errorf("auth模块不存在") } if authModule != nil { if authMod, ok := authModule.(*auth.Module); ok { return authMod.SyncRoutes(app) } } return nil } func printBanner() { fmt.Print("\033[92m") fmt.Println(` ██████╗ ██████╗ ███████╗ █████╗ ███████╗████████╗███████╗███████╗ ██╔════╝ ██╔═══██╗██╔════╝██╔══██╗██╔════╝╚══██╔══╝██╔════╝██╔══██║ ██║ ███╗██║ ██║█████╗ ███████║███████╗ ██║ █████╗ ██████║ ██║ ██║██║ ██║██╔══╝ ██╔══██║╚════██║ ██║ ██╔══╝ ██╔══██╗ ╚██████╔╝╚██████╔╝██╗ ██║ ██║███████║ ██║ ███████╗██║ ██║ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ `) fmt.Print("\033[0m") }