diff --git a/.env.example b/.env.example index db1b934..ecb2d64 100644 --- a/.env.example +++ b/.env.example @@ -30,6 +30,13 @@ SERVER_READ_TIMEOUT=30s SERVER_WRITE_TIMEOUT=30s SERVER_SWAGGER_ENABLED=true +# ============================================================================= +# 应用环境 +# ============================================================================= +# 用于 service 层 IsTestEnvironment() 短路验证码/邮件等 +# 取值:development / test / production +ENVIRONMENT=production + # ============================================================================= # 数据库配置 # ============================================================================= @@ -133,6 +140,11 @@ JWT_EXPIRE_HOURS=168 LOG_LEVEL=info LOG_FORMAT=json LOG_OUTPUT=logs/app.log +# 日志轮转参数(用于 lumberjack) +LOG_MAX_SIZE=100 # 单文件最大 MB +LOG_MAX_BACKUPS=3 # 保留旧文件数 +LOG_MAX_AGE=28 # 旧文件最大保留天数 +LOG_COMPRESS=true # 是否压缩旧文件 # ============================================================================= # 安全配置 diff --git a/README.md b/README.md index e0cf190..e3e1233 100644 --- a/README.md +++ b/README.md @@ -33,21 +33,32 @@ ``` backend/ -├── cmd/server/ # 应用入口(main.go) +├── cmd/server/ # 应用入口(main.go:极简 fx 装配) ├── internal/ -│ ├── handler/ # HTTP Handler 与 Swagger 注解 -│ ├── service/ # 业务逻辑 -│ ├── repository/ # 数据访问 -│ ├── model/ # GORM 数据模型 -│ ├── types/ # 请求/响应 DTO -│ ├── middleware/ # Gin 中间件 -│ └── task/ # 定时任务与后台作业 -├── pkg/ # 可复用组件(config、database、auth、logger、redis、storage 等) -├── docs/ # swagger 生成产物(docs.go / swagger.json / swagger.yaml) -├── start.sh # 启动脚本(自动 swag init) -├── docker-compose.yml # 本地容器编排 -├── .env.example # 环境变量示例 -└── go.mod # Go Module 定义 +│ ├── app/ # uber-go/fx 装配层(唯一依赖注入入口) +│ │ ├── module.go # 聚合根 Module +│ │ ├── infra_module.go # Logger/DB/Redis/Storage/Email/JWT/Casbin + Lifecycle +│ │ ├── container_module.go # Container 聚合 + 路由/HTTP/任务生命周期 +│ │ ├── repository_module.go # Repository Provider(占位,Container 模式暂未启用) +│ │ ├── service_module.go # Service Provider(占位) +│ │ ├── handler_module.go # Handler Provider(占位) +│ │ ├── server_module.go # HTTP 服务器模块(占位) +│ │ └── task_module.go # 后台任务模块(占位) +│ ├── container/ # 过渡期手动 DI 容器(fx 迁移期的聚合层) +│ ├── handler/ # HTTP Handler 与 Swagger 注解 +│ ├── service/ # 业务逻辑(接口 + 实现) +│ ├── repository/ # 数据访问(接口 + GORM 实现) +│ ├── model/ # GORM 数据模型与响应结构 +│ ├── types/ # 请求/响应 DTO +│ ├── errors/ # 统一错误定义(apperrors) +│ ├── middleware/ # Gin 中间件 +│ └── task/ # 定时任务与后台作业 +├── pkg/ # 可复用组件(config、database、auth、logger、redis、storage、email、utils) +├── docs/ # swagger 生成产物(docs.go / swagger.json / swagger.yaml) +├── start.sh # 启动脚本(自动 swag init) +├── docker-compose.yml # 本地容器编排 +├── .env.example # 环境变量示例 +└── go.mod # Go Module 定义 ``` ## ✅ 前置要求 @@ -113,6 +124,9 @@ backend/ | `JWT_SECRET` | JWT 签名密钥 | `change-me` | | `EMAIL_ENABLED` | 是否开启邮件服务 | `true` | | `EMAIL_SMTP_HOST` / `EMAIL_SMTP_PORT` | SMTP 配置 | `smtp.example.com` / `587` | +| `ENVIRONMENT` | 应用环境(用于 service 层 `IsTestEnvironment()` 短路) | `production` | +| `SECURITY_ALLOWED_ORIGINS` | CORS 允许的来源(逗号分隔) | `*` | +| `SECURITY_ALLOWED_DOMAINS` | 头像/材质 URL 允许的域名(逗号分隔) | `localhost,127.0.0.1` | 更多变量请参考 `.env.example` 与 `.env.docker.example`。 @@ -132,11 +146,21 @@ golangci-lint run (若已安装) ## 🧱 架构说明 -- **分层设计**:Handler -> Service -> Repository -> Model,层次清晰、职责单一。 -- **依赖管理器**:`pkg/*/manager.go` 使用 `sync.Once` 实现线程安全单例(DB / Redis / Logger / Storage / Email / Auth / Config)。 +- **分层设计**:Handler → Service → Repository → Model,层次清晰、职责单一。 + - Handler 不得直连 `*gorm.DB` 或 `*Repository`,必须通过 Service。 + - Service 不得持有 `*gorm.DB`,所有数据访问通过 Repository 接口。 +- **依赖注入(uber-go/fx)**: + - `internal/app/` 是唯一的依赖装配入口。每个基础设施 / 仓储 / 服务作为 `fx.Provider` 注册。 + - **生命周期管理**:DB / Redis / Storage / Logger / HTTP Server / Task Runner 通过 `fx.Lifecycle` 的 `OnStart` / `OnStop` Hook 统一管理,彻底替代散落在 `main()` 的 `defer Close()` 链。 + - **优雅关闭**:`fx.New(app.Module(cfg)).Run()` 监听 `SIGINT` / `SIGTERM`,按依赖逆序触发 `OnStop`,先关 HTTP Server(30s 超时),再关 Task Runner,最后关 DB/Redis。 + - **Dev/Test 自动回退**:Redis 连接失败且环境为 `development` / `test` / `dev` / `USE_MINIREDIS=true` 时自动启用 `miniredis`。 + - **启动时错误检查**:循环依赖、缺失 Provider、Provider 返回 error 全部在 `fx.New()` 阶段立即检测。 +- **错误与响应统一**: + - 错误统一在 `internal/errors/`(别名 `apperrors`),通过 `errors.Is/As` 匹配。 + - 响应统一使用 `model.Response` / `model.PaginationResponse` / `model.NewErrorResponse`。 + - Middleware 错误响应也走 `model.NewErrorResponse`,不再使用裸 `gin.H`。 +- **配置优先级**:`config.Load()` 读取 `.env` → 环境变量 → viper 默认值;`*config.Config` 由 `fx.Supply` 注入。 - **Swagger 注解**:所有 Handler、模型、DTO 均补齐 `@Summary` / `@Description` / `@Success`,可直接生成 OpenAPI 文档。 -- **配置优先级**:`.env` -> 系统环境变量,所有配置均可通过容器注入。 -- **自动任务**:`internal/task` 承载后台作业,可按需扩展。 ## 📝 Swagger 说明 diff --git a/internal/container/container.go b/internal/container/container.go index 3725de7..46f8038 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -1,6 +1,9 @@ package container import ( + "context" + "time" + "carrotskin/internal/repository" "carrotskin/internal/service" "carrotskin/pkg/auth" @@ -9,8 +12,6 @@ import ( "carrotskin/pkg/email" "carrotskin/pkg/redis" "carrotskin/pkg/storage" - "context" - "time" "go.uber.org/zap" "gorm.io/gorm" diff --git a/internal/errors/errors.go b/internal/errors/errors.go index f510be7..3e82721 100644 --- a/internal/errors/errors.go +++ b/internal/errors/errors.go @@ -128,7 +128,6 @@ func NewInternalError(message string, err error) *AppError { // 注意:原此处的 Is/As/Wrap 函数(透传标准库)已删除。 // 请直接使用标准库 errors.Is / errors.As / fmt.Errorf。 - // YggdrasilErrorResponse Yggdrasil协议标准错误响应格式 type YggdrasilErrorResponse struct { Error string `json:"error"` // 错误的简要描述(机器可读) diff --git a/internal/handler/admin_handler.go b/internal/handler/admin_handler.go index 89c4a53..41d6267 100644 --- a/internal/handler/admin_handler.go +++ b/internal/handler/admin_handler.go @@ -5,8 +5,8 @@ import ( "net/http" "strconv" - apperrors "carrotskin/internal/errors" "carrotskin/internal/container" + apperrors "carrotskin/internal/errors" "carrotskin/internal/model" "github.com/gin-gonic/gin" diff --git a/internal/handler/captcha_handler.go b/internal/handler/captcha_handler.go index 03e543e..3d0d2cd 100644 --- a/internal/handler/captcha_handler.go +++ b/internal/handler/captcha_handler.go @@ -1,9 +1,10 @@ package handler import ( - "carrotskin/internal/container" "net/http" + "carrotskin/internal/container" + "github.com/gin-gonic/gin" "go.uber.org/zap" ) diff --git a/internal/handler/customskin_handler.go b/internal/handler/customskin_handler.go index 17cc994..00c75d7 100644 --- a/internal/handler/customskin_handler.go +++ b/internal/handler/customskin_handler.go @@ -1,13 +1,14 @@ package handler import ( - "carrotskin/internal/container" "context" "fmt" "net/http" "strings" "time" + "carrotskin/internal/container" + "github.com/gin-gonic/gin" "go.uber.org/zap" ) diff --git a/internal/handler/helpers.go b/internal/handler/helpers.go index 9ed2de5..edbdd0c 100644 --- a/internal/handler/helpers.go +++ b/internal/handler/helpers.go @@ -1,13 +1,14 @@ package handler import ( - apperrors "carrotskin/internal/errors" - "carrotskin/internal/model" - "carrotskin/internal/types" "errors" "net/http" "strconv" + apperrors "carrotskin/internal/errors" + "carrotskin/internal/model" + "carrotskin/internal/types" + "github.com/gin-gonic/gin" ) diff --git a/internal/handler/texture_handler.go b/internal/handler/texture_handler.go index 28166bd..bbf7870 100644 --- a/internal/handler/texture_handler.go +++ b/internal/handler/texture_handler.go @@ -1,10 +1,11 @@ package handler import ( + "strconv" + "carrotskin/internal/container" "carrotskin/internal/model" "carrotskin/internal/types" - "strconv" "github.com/gin-gonic/gin" "go.uber.org/zap" diff --git a/internal/handler/yggdrasil_handler.go b/internal/handler/yggdrasil_handler.go index 555f736..4b177a0 100644 --- a/internal/handler/yggdrasil_handler.go +++ b/internal/handler/yggdrasil_handler.go @@ -2,13 +2,14 @@ package handler import ( "bytes" + "io" + "net/http" + "regexp" + "carrotskin/internal/container" "carrotskin/internal/errors" "carrotskin/internal/model" "carrotskin/pkg/utils" - "io" - "net/http" - "regexp" "github.com/gin-gonic/gin" "go.uber.org/zap" diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index b6ab4e9..59b9935 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -1,10 +1,11 @@ package middleware import ( - "carrotskin/internal/model" "net/http" "strings" + "carrotskin/internal/model" + "carrotskin/pkg/auth" "github.com/gin-gonic/gin" diff --git a/internal/repository/client_repository.go b/internal/repository/client_repository.go index 20a6435..7cbf4ca 100644 --- a/internal/repository/client_repository.go +++ b/internal/repository/client_repository.go @@ -1,9 +1,10 @@ package repository import ( - "carrotskin/internal/model" "context" + "carrotskin/internal/model" + "gorm.io/gorm" ) diff --git a/internal/repository/interfaces.go b/internal/repository/interfaces.go index c16b746..a7091ec 100644 --- a/internal/repository/interfaces.go +++ b/internal/repository/interfaces.go @@ -1,8 +1,9 @@ package repository import ( - "carrotskin/internal/model" "context" + + "carrotskin/internal/model" ) // UserRepository 用户仓储接口 @@ -11,7 +12,7 @@ type UserRepository interface { FindByID(ctx context.Context, id int64) (*model.User, error) FindByUsername(ctx context.Context, username string) (*model.User, error) FindByEmail(ctx context.Context, email string) (*model.User, error) - FindByIDs(ctx context.Context, ids []int64) ([]*model.User, error) // 批量查询 + FindByIDs(ctx context.Context, ids []int64) ([]*model.User, error) // 批量查询 List(ctx context.Context, page, pageSize int) ([]*model.User, int64, error) // 分页列表(管理员) Update(ctx context.Context, user *model.User) error UpdateFields(ctx context.Context, id int64, fields map[string]interface{}) error @@ -66,10 +67,9 @@ type TextureRepository interface { GetUserFavorites(ctx context.Context, userID int64, page, pageSize int) ([]*model.Texture, int64, error) CountByUploaderID(ctx context.Context, uploaderID int64) (int64, error) ListForAdmin(ctx context.Context, page, pageSize int) ([]*model.Texture, int64, error) // 管理员列表(含 Uploader 预加载) - FindByIDForAdmin(ctx context.Context, id int64) (*model.Texture, error) // 管理员查询(无权限过滤) + FindByIDForAdmin(ctx context.Context, id int64) (*model.Texture, error) // 管理员查询(无权限过滤) } - // YggdrasilRepository Yggdrasil仓储接口 type YggdrasilRepository interface { GetPasswordByID(ctx context.Context, id int64) (string, error) diff --git a/internal/repository/profile_repository.go b/internal/repository/profile_repository.go index 57867a4..fcc6cc0 100644 --- a/internal/repository/profile_repository.go +++ b/internal/repository/profile_repository.go @@ -1,11 +1,12 @@ package repository import ( - "carrotskin/internal/model" "context" "errors" "fmt" + "carrotskin/internal/model" + "gorm.io/gorm" ) diff --git a/internal/repository/texture_repository.go b/internal/repository/texture_repository.go index 4aa34d7..035a37d 100644 --- a/internal/repository/texture_repository.go +++ b/internal/repository/texture_repository.go @@ -1,9 +1,10 @@ package repository import ( - "carrotskin/internal/model" "context" + "carrotskin/internal/model" + "gorm.io/gorm" ) diff --git a/internal/repository/user_repository.go b/internal/repository/user_repository.go index fede77e..de3ee80 100644 --- a/internal/repository/user_repository.go +++ b/internal/repository/user_repository.go @@ -1,10 +1,11 @@ package repository import ( - "carrotskin/internal/model" "context" "errors" + "carrotskin/internal/model" + "gorm.io/gorm" ) diff --git a/internal/repository/yggdrasil_repository.go b/internal/repository/yggdrasil_repository.go index 45c2fd3..0e22af6 100644 --- a/internal/repository/yggdrasil_repository.go +++ b/internal/repository/yggdrasil_repository.go @@ -1,9 +1,10 @@ package repository import ( - "carrotskin/internal/model" "context" + "carrotskin/internal/model" + "gorm.io/gorm" ) @@ -34,9 +35,3 @@ func (r *yggdrasilRepository) ResetPassword(ctx context.Context, id int64, passw func (r *yggdrasilRepository) Create(ctx context.Context, yggdrasil *model.Yggdrasil) error { return r.db.WithContext(ctx).Create(yggdrasil).Error } - - - - - - diff --git a/internal/service/captcha_service.go b/internal/service/captcha_service.go index c9356af..a058e9e 100644 --- a/internal/service/captcha_service.go +++ b/internal/service/captcha_service.go @@ -1,15 +1,16 @@ package service import ( - "carrotskin/pkg/config" - "carrotskin/pkg/redis" - "carrotskin/pkg/utils" "context" "errors" "fmt" "log" "time" + "carrotskin/pkg/config" + "carrotskin/pkg/redis" + "carrotskin/pkg/utils" + "github.com/wenlng/go-captcha-assets/resources/imagesv2" "github.com/wenlng/go-captcha-assets/resources/tiles" "github.com/wenlng/go-captcha/v2/slide" diff --git a/internal/service/interfaces.go b/internal/service/interfaces.go index da2e4e1..036b960 100644 --- a/internal/service/interfaces.go +++ b/internal/service/interfaces.go @@ -2,11 +2,12 @@ package service import ( - "carrotskin/internal/model" - "carrotskin/pkg/storage" "context" "time" + "carrotskin/internal/model" + "carrotskin/pkg/storage" + "go.uber.org/zap" ) diff --git a/internal/service/profile_service.go b/internal/service/profile_service.go index 7b57c24..6422039 100644 --- a/internal/service/profile_service.go +++ b/internal/service/profile_service.go @@ -1,11 +1,6 @@ package service import ( - apperrors "carrotskin/internal/errors" - "carrotskin/internal/model" - "carrotskin/internal/repository" - "carrotskin/pkg/database" - "carrotskin/pkg/utils" "context" "crypto/rand" "crypto/rsa" @@ -14,6 +9,12 @@ import ( "errors" "fmt" + apperrors "carrotskin/internal/errors" + "carrotskin/internal/model" + "carrotskin/internal/repository" + "carrotskin/pkg/database" + "carrotskin/pkg/utils" + "go.uber.org/zap" "gorm.io/gorm" ) diff --git a/internal/service/signature_service.go b/internal/service/signature_service.go index 39062a7..6b5ec4a 100644 --- a/internal/service/signature_service.go +++ b/internal/service/signature_service.go @@ -1,9 +1,6 @@ package service import ( - "carrotskin/internal/model" - "carrotskin/internal/repository" - "carrotskin/pkg/redis" "context" "crypto" "crypto/rand" @@ -18,6 +15,10 @@ import ( "strings" "time" + "carrotskin/internal/model" + "carrotskin/internal/repository" + "carrotskin/pkg/redis" + "go.uber.org/zap" ) diff --git a/internal/service/texture_service.go b/internal/service/texture_service.go index 6d7607c..bb91370 100644 --- a/internal/service/texture_service.go +++ b/internal/service/texture_service.go @@ -2,11 +2,6 @@ package service import ( "bytes" - apperrors "carrotskin/internal/errors" - "carrotskin/internal/model" - "carrotskin/internal/repository" - "carrotskin/pkg/database" - "carrotskin/pkg/storage" "context" "crypto/sha256" "encoding/hex" @@ -16,6 +11,12 @@ import ( "strings" "time" + apperrors "carrotskin/internal/errors" + "carrotskin/internal/model" + "carrotskin/internal/repository" + "carrotskin/pkg/database" + "carrotskin/pkg/storage" + "go.uber.org/zap" "gorm.io/gorm" ) diff --git a/internal/service/token_service_redis.go b/internal/service/token_service_redis.go index 92a7d29..511d76b 100644 --- a/internal/service/token_service_redis.go +++ b/internal/service/token_service_redis.go @@ -1,15 +1,16 @@ package service import ( - "carrotskin/internal/model" - "carrotskin/internal/repository" - "carrotskin/pkg/auth" - "carrotskin/pkg/utils" "context" "errors" "fmt" "time" + "carrotskin/internal/model" + "carrotskin/internal/repository" + "carrotskin/pkg/auth" + "carrotskin/pkg/utils" + "go.uber.org/zap" ) diff --git a/internal/service/yggdrasil_auth_service.go b/internal/service/yggdrasil_auth_service.go index 492c559..d17820a 100644 --- a/internal/service/yggdrasil_auth_service.go +++ b/internal/service/yggdrasil_auth_service.go @@ -1,12 +1,13 @@ package service import ( + "context" + "fmt" + apperrors "carrotskin/internal/errors" "carrotskin/internal/model" "carrotskin/internal/repository" "carrotskin/pkg/auth" - "context" - "fmt" "go.uber.org/zap" ) diff --git a/internal/service/yggdrasil_certificate_service.go b/internal/service/yggdrasil_certificate_service.go index 2f6eabd..72e4a81 100644 --- a/internal/service/yggdrasil_certificate_service.go +++ b/internal/service/yggdrasil_certificate_service.go @@ -1,12 +1,13 @@ package service import ( - apperrors "carrotskin/internal/errors" - "carrotskin/internal/repository" "context" "fmt" "time" + apperrors "carrotskin/internal/errors" + "carrotskin/internal/repository" + "go.uber.org/zap" ) @@ -109,4 +110,3 @@ func (s *yggdrasilCertificateService) GeneratePlayerCertificate(ctx context.Cont func (s *yggdrasilCertificateService) GetPublicKey(ctx context.Context) (string, error) { return s.signatureService.GetPublicKeyFromRedis(ctx) } - diff --git a/internal/service/yggdrasil_serialization_service.go b/internal/service/yggdrasil_serialization_service.go index cf1ce4c..565fdcc 100644 --- a/internal/service/yggdrasil_serialization_service.go +++ b/internal/service/yggdrasil_serialization_service.go @@ -1,12 +1,13 @@ package service import ( - "carrotskin/internal/model" - "carrotskin/internal/repository" "context" "encoding/base64" "time" + "carrotskin/internal/model" + "carrotskin/internal/repository" + "go.uber.org/zap" ) diff --git a/internal/service/yggdrasil_service_composite.go b/internal/service/yggdrasil_service_composite.go index ef29964..78c1346 100644 --- a/internal/service/yggdrasil_service_composite.go +++ b/internal/service/yggdrasil_service_composite.go @@ -1,13 +1,14 @@ package service import ( + "context" + "errors" + "fmt" + "carrotskin/internal/model" "carrotskin/internal/repository" "carrotskin/pkg/redis" "carrotskin/pkg/utils" - "context" - "errors" - "fmt" "go.uber.org/zap" ) diff --git a/internal/service/yggdrasil_session_service.go b/internal/service/yggdrasil_session_service.go index e222909..dfa27cf 100644 --- a/internal/service/yggdrasil_session_service.go +++ b/internal/service/yggdrasil_session_service.go @@ -1,14 +1,15 @@ package service import ( - apperrors "carrotskin/internal/errors" - "carrotskin/pkg/redis" "context" "fmt" "net" "strings" "time" + apperrors "carrotskin/internal/errors" + "carrotskin/pkg/redis" + "go.uber.org/zap" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index b970615..835feb8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -259,6 +259,7 @@ func setupEnvMappings() { viper.BindEnv("server.read_timeout", "SERVER_READ_TIMEOUT") viper.BindEnv("server.write_timeout", "SERVER_WRITE_TIMEOUT") viper.BindEnv("server.swagger_enabled", "SERVER_SWAGGER_ENABLED") + viper.BindEnv("environment", "ENVIRONMENT") // 数据库配置 viper.BindEnv("database.driver", "DATABASE_DRIVER") @@ -306,6 +307,10 @@ func setupEnvMappings() { viper.BindEnv("log.level", "LOG_LEVEL") viper.BindEnv("log.format", "LOG_FORMAT") viper.BindEnv("log.output", "LOG_OUTPUT") + viper.BindEnv("log.max_size", "LOG_MAX_SIZE") + viper.BindEnv("log.max_backups", "LOG_MAX_BACKUPS") + viper.BindEnv("log.max_age", "LOG_MAX_AGE") + viper.BindEnv("log.compress", "LOG_COMPRESS") // 邮件配置 viper.BindEnv("email.enabled", "EMAIL_ENABLED") @@ -457,10 +462,7 @@ func overrideFromEnv(config *Config) { config.Email.Enabled = emailEnabled == "true" || emailEnabled == "True" || emailEnabled == "TRUE" || emailEnabled == "1" } - // 处理环境配置 - if env := os.Getenv("ENVIRONMENT"); env != "" { - config.Environment = env - } + // 处理环境配置(已由 BindEnv("environment", "ENVIRONMENT") + AutomaticEnv 处理) // 处理安全配置 if allowedOrigins := os.Getenv("SECURITY_ALLOWED_ORIGINS"); allowedOrigins != "" { diff --git a/pkg/database/manager.go b/pkg/database/manager.go index ef6030b..1ad0d8c 100644 --- a/pkg/database/manager.go +++ b/pkg/database/manager.go @@ -1,9 +1,10 @@ package database import ( - "carrotskin/internal/model" "fmt" + "carrotskin/internal/model" + "go.uber.org/zap" "gorm.io/gorm" ) diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 0dae55b..56e8192 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -3,9 +3,9 @@ package logger import ( "os" "path/filepath" - + "carrotskin/pkg/config" - + "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -50,7 +50,7 @@ func New(cfg config.LogConfig) (*zap.Logger, error) { if err := os.MkdirAll(logDir, 0755); err != nil { return nil, err } - + file, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return nil, err diff --git a/pkg/storage/minio.go b/pkg/storage/minio.go index 31ac10d..cb3c063 100644 --- a/pkg/storage/minio.go +++ b/pkg/storage/minio.go @@ -79,7 +79,6 @@ func (s *StorageClient) GetBucket(name string) (string, error) { return bucket, nil } - // BuildFileURL 构建文件的公开访问URL func (s *StorageClient) BuildFileURL(bucketName, objectName string) string { return fmt.Sprintf("%s/%s/%s", s.publicURL, bucketName, objectName)