2.8 KiB
2.8 KiB
Gin Mode Config Design
日期:2026-07-02
目标
移除 internal/api.NewRouter 中硬编码的:
gin.SetMode(gin.ReleaseMode)
改为通过项目配置控制 Gin mode。
当前问题
当前 NewRouter 写死 release mode。这个做法有两个问题:
- 开发、测试、生产不能用同一套配置机制控制 Gin mode。
- Gin mode 是运行配置,不应该藏在 router 代码里。
非目标
本次不做:
- 不改变 API 路径、method、响应结构。
- 不改变 Gin middleware。
- 不改变 slog 日志策略。
- 不引入新依赖。
- 不实现 auth/CORS/WebSocket/Git/LSP/Agent。
配置设计
configs/config.yaml 增加:
gin:
mode: "release"
pkg/config 增加:
type GinConfig struct {
Mode string `yaml:"mode"`
}
Config 增加:
Gin GinConfig `yaml:"gin"`
默认值:
release
环境变量覆盖:
CODESPACE_GIN_MODE
合法值:
debugreleasetest
非法值在 config.Load 阶段返回错误。不要等到 router 初始化才失败。
Router 设计
api.NewRouter 签名改为:
func NewRouter(
workspaces *service.WorkspaceService,
files *service.FileService,
processes *service.ProcessService,
lg *slog.Logger,
ginMode string,
) *gin.Engine
内部:
gin.SetMode(ginMode)
r := gin.New()
NewRouter 不负责校验 mode。校验属于 config 层。
main.go 设计
router := api.NewRouter(workspaceSvc, fileSvc, processSvc, lg, cfg.Gin.Mode)
测试设计
config tests
覆盖:
- 默认 mode 是
release - YAML 可设置
debug - env
CODESPACE_GIN_MODE可覆盖为test - 非法 mode 返回错误
router tests
所有测试调用:
NewRouter(wsSvc, fileSvc, procSvc, nil, gin.TestMode)
这样测试明确使用 Gin test mode。
validation
必须通过:
gofmt -w cmd internal pkg
go test ./...
grep -R "gin.SetMode(gin.ReleaseMode)" cmd internal pkg || true
grep -R "gin\.Default\|gin\.Logger" cmd internal pkg || true
预期:
- 不再出现
gin.SetMode(gin.ReleaseMode) - 不出现
gin.Default/gin.Logger
风险与处理
- 风险:Gin mode 是全局状态,测试互相污染。处理:router tests 统一传
gin.TestMode。 - 风险:非法 mode 到运行时才失败。处理:config.Load 阶段校验。
- 风险:把 Gin mode 塞进
server配置造成语义混乱。处理:独立gin配置块。
完成标准
configs/config.yaml有gin.mode。config.Default()返回Gin.Mode == "release"。CODESPACE_GIN_MODE可覆盖 mode。- 非法 mode 让
config.Load返回错误。 NewRouter不再硬编码gin.ReleaseMode。main.go从 config 传入 Gin mode。go test ./...通过。- server smoke test 通过。