初始化
引擎初始化
engineInit 创建并配置 Gin 引擎,注册内置中间件和验证器,并注入初始化上下文
引擎初始化
engineInit 方法创建并配置 Gin 引擎,注册内置中间件、自定义验证器,并将初始化上下文注入到每个 HTTP 请求。
engineInit
// 私有方法,在 Register 流程中自动调用
func (r *Reg) engineInit()实现细节
func (r *Reg) engineInit() {
log := xLog.WithName(xLog.NamedINIT)
log.Debug(r.Init.Ctx, "初始化 GIN 引擎")
if !xCtxUtil.IsDebugMode() {
gin.SetMode(gin.ReleaseMode)
}
// 注册验证器和翻译器
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
xVaild.RegisterTranslator(v)
xVaild.RegisterCustomValidators(v)
}
// 创建 Gin 引擎并注册中间件
r.Serve = gin.New(func(engine *gin.Engine) {
engine.Use(xHelper.RequestContext())
engine.Use(xHelper.PanicRecovery())
engine.Use(xHelper.HttpLogger())
engine.Use(injectContext(r.Init.Ctx)) // 注入初始化上下文
})
}上下文注入
关键改进:将节点管理器的上下文注入到每个 HTTP 请求:
// 注入初始化上下文到每个请求
func injectContext(ctx context.Context) func(c *gin.Context) {
return func(c *gin.Context) {
// 将初始化上下文合并到请求上下文
c.Request = c.Request.WithContext(ctx)
c.Next()
}
}这意味着:
- 所有通过节点注入的资源(数据库、Redis 等)都可以通过
c.Request.Context()获取 - 业务代码使用标准
context.Context,实现框架解耦
内置中间件
| 中间件 | 说明 |
|---|---|
xHelper.RequestContext() | 请求上下文处理,生成请求 ID 等 |
xHelper.PanicRecovery() | Panic 恢复,防止单个请求崩溃影响整个服务 |
xHelper.HttpLogger() | HTTP 请求日志记录 |
injectContext(ctx) | 注入初始化上下文到请求 |
运行模式
根据 DEBUG 环境变量自动切换 Gin 运行模式:
| 环境变量 | Gin 模式 | 说明 |
|---|---|---|
DEBUG=true | Debug | 输出详细调试信息 |
DEBUG=false 或未设置 | Release | 生产模式,关闭调试输出 |
验证器
翻译器
注册中文翻译器,将验证错误信息翻译为中文:
type CreateUserReq struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
}
// 验证失败时返回中文错误信息
// "Name 为必填字段"
// "Email 必须是有效的邮箱地址"自定义验证器
框架预置了常用的自定义验证器:
type CreateUserReq struct {
Phone string `json:"phone" binding:"required,phone"` // 手机号验证
IDCard string `json:"id_card" binding:"required,idcard"` // 身份证验证
}使用引擎
初始化完成后,通过 reg.Serve 访问 Gin 引擎:
reg := xReg.Register(context.Background(), nodeList)
// 注册路由
reg.Serve.GET("/api/users", userHandler.List)
reg.Serve.POST("/api/users", userHandler.Create)
reg.Serve.PUT("/api/users/:id", userHandler.Update)
// 路由分组
api := reg.Serve.Group("/api/v1")
{
api.GET("/products", productHandler.List)
api.POST("/orders", orderHandler.Create)
}
// 启动服务
reg.Serve.Run(":8080")在 Handler 中获取资源
func MyHandler(c *gin.Context) {
// 获取标准上下文(包含所有注入的资源)
ctx := c.Request.Context()
// 使用 xCtxUtil 获取资源
db := xCtxUtil.MustGetDB(ctx)
rdb := xCtxUtil.MustGetRDB(ctx)
node := xCtxUtil.GetSnowflakeNode(ctx)
}