package app import ( "context" "github.com/go-redis/redis/v8" "github.com/goccy/go-json" "github.com/gofiber/fiber/v2" "github.com/spf13/viper" "gofiber.study.skcks.cn/common/config" "gofiber.study.skcks.cn/common/errorx" "gofiber.study.skcks.cn/common/logger" "gofiber.study.skcks.cn/common/response" "gofiber.study.skcks.cn/controller" "gofiber.study.skcks.cn/global" "xorm.io/xorm" ) var App *fiber.App func Run() { err := viper.Unmarshal(global.Config) if err != nil { logger.Log.Fatalf("配置文件解析失败: %s", err) } mainAppExec(func() { logger.Log.Infof("\n%#v", global.Config) }) reloadRedis(global.Config) reloadDataSources(global.Config) App = reloadApp(global.Config) if err := App.Listen(global.Config.Server.Addr); err != nil { logger.Log.Fatalf("[x] [Fiber] 致命错误: %s", err) } } func reloadRedis(c *config.BasicConfig) { if global.Redis != nil { _ = global.Redis.Close() } r := redis.NewClient(&redis.Options{ Addr: c.Redis.Addr, Password: c.Redis.Pass, DB: c.Redis.DB, }) ctx := context.Background() _, err := r.Ping(ctx).Result() if err != nil { logger.Log.Fatalln("[x] [Redis] 连接失败: %s", err) } mainAppExec(func() { logger.Log.Infoln("[√] [Redis] 连接成功") }) global.Redis = r } func reloadDataSources(c *config.BasicConfig) { if global.DataSources != nil { _ = global.DataSources.Close() } connGroup, err := xorm.NewEngineGroup("mysql", c.Mysql.DataSources) if err != nil { logger.Log.Fatalf("[x] [数据源] 致命错误: %s", err) } mainAppExec(func() { logger.Log.Infoln("[√] [数据源] 初始化完成") }) global.DataSources = connGroup if c.Mysql.AutoSync && !fiber.IsChild() { global.SyncModelToDataSource() } } func reloadApp(c *config.BasicConfig) *fiber.App { if App != nil { _ = App.Shutdown() } app := fiber.New(fiber.Config{ JSONEncoder: json.Marshal, JSONDecoder: json.Unmarshal, Prefork: c.Server.PreFork, CaseSensitive: c.Server.CaseSensitive, StrictRouting: c.Server.StrictRouting, ServerHeader: c.Server.ServerHeader, ErrorHandler: func(ctx *fiber.Ctx, err error) error { code := fiber.StatusInternalServerError if e, ok := err.(*fiber.Error); ok { code = e.Code } err = ctx.Status(code).JSON(errorx.NewDefaultError(err.Error())) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") } return nil }, }) if c.Server.EnableRoutesMsg { routes(app) } controller.SwaggerHandler(app) controller.RegisterController(app) controller.HelloWorld(app) controller.ErrorHandler(app) app.Hooks().OnListen(func() error { mainAppExec(func() { logger.Log.Infoln("[√] [服务启动完成]") }) return nil }) return app } // mainAppExec 仅主进程执行 忽略子进程 func mainAppExec(fn func()) { if !fiber.IsChild() { fn() } } // routes // @Summary 获取所有路由 // @Description 获取所有路由信息 // @Tags Routes // @Accept json // @Produce json // @Success 200 {object} response.Response{data=[][]fiber.Route} // @Router /routes [get] func routes(app *fiber.App) { app.Get("/routes", func(ctx *fiber.Ctx) error { return ctx.JSON(response.NewResponse(app.Stack())) }) }