Helper 全局访问器
Helper 全局访问器
pkg/helper/ 提供了一组对常见基础设施服务的便捷访问函数。它们是对 container.MustGet[T]() 的薄薄一层封装,目标是让业务代码用起来像访问全局对象一样自然,但底层仍然是 DI 容器单例。
为什么有 Helper
虽然 DI 容器和反射注入功能强大,但在大多数业务文件中并不希望写:
db := container.MustGet[*gorm.DB]()这种写法既冗长又需要导入 container 包。Helper 把最常用的基础设施抽出成顶层函数:
db := helper.GetDatabase()行为完全等价(底层就是 container.MustGet),但更易读,且可在任意位置使用,无需先 Inject。
函数列表
所有函数都位于 cnb.cool/mliev/open/go-web/pkg/helper。
| 函数 | 返回类型 | 说明 |
|---|---|---|
GetDatabase() |
*gorm.DB |
GORM 数据库实例 |
GetLogger() |
gsr.Logger |
全局结构化日志 |
GetCache() |
gsr.Cacher |
缓存接口(根据 cache.driver 选择实现) |
GetRedis() |
Redis 客户端 | Redis 操作客户端 |
GetConfig() |
gsr.Provider |
配置中心(Get* / Set / ... ) |
GetEnv() |
gsr.EnvReader |
Viper 环境变量读取器 |
GetRequestLogger(c) |
gsr.Logger |
当前请求的 logger(带 traceId,从上下文取出) |
注意:除
GetRequestLogger外,所有函数都基于MustGet,如果对应服务未注册或Build()失败,会 panic。这通常意味着你的AppProvider.Assemblies()没有把对应的 Assembly 放进装配链。
典型用法
数据库
import "cnb.cool/mliev/open/go-web/pkg/helper"
db := helper.GetDatabase()
var users []model.User
if err := db.Where("status = ?", "active").Find(&users).Error; err != nil {
return err
}日志(全局)
helper.GetLogger().Info("user created", gsr.String("username", u.Username))
helper.GetLogger().Error("update failed", gsr.Error(err))日志(请求级,带 traceId)
在 Controller 或中间件里使用:
func (UserController) GetUser(c httpInterfaces.RouterContextInterface) {
log := helper.GetRequestLogger(c)
log.Info("handling get user", gsr.String("id", c.Param("id")))
// ...
}GetRequestLogger(c) 会从上下文中读取 helper.RequestLoggerKey 这个 key 对应的 logger;如果未设置,自动回退到 GetLogger()。框架默认在请求开始时由 HTTP server 注入一个带 traceId 字段的 logger,所以只要使用 GetRequestLogger 就能获得请求关联的日志。
缓存
cache := helper.GetCache()
if val, err := cache.Get("user:42"); err == nil && val != nil {
return val, nil
}
cache.Set("user:42", user, 5*time.Minute)具体实现取决于 cache.driver 配置:memory / redis / none。
Redis
ctx := c.Request.Context() // 或 context.Background()
client := helper.GetRedis()
if err := client.Set(ctx, "key", "value", 0).Err(); err != nil {
return err
}GetRedis() 返回的是经过封装的 Redis 客户端,具体类型见 pkg/server/redis/。
配置
cfg := helper.GetConfig()
mode := cfg.GetString("app.mode", "debug")
port := cfg.GetInt("server.port", 8080)环境变量
env := helper.GetEnv()
val := env.GetString("MY_VAR", "fallback")通常优先使用 GetConfig,因为它是经过 InitConfig 默认值聚合的版本;只有在需要读取未在 autoload/ 中声明的配置项时才直接走 GetEnv。
在测试中替换 Helper 返回值
由于 Helper 内部走的是 DI 容器,你可以在测试 setUp 阶段通过更高优先级的 Provider 注入 mock 实例:
func TestUserService(t *testing.T) {
mockDB := newMockGormDB()
container.Register(container.NewSimpleProviderWithPriority(
reflect.TypeFor[*gorm.DB](),
mockDB,
100, // 高于默认优先级 0
))
defer container.Reset(reflect.TypeFor[*gorm.DB]())
// 此后 helper.GetDatabase() 返回 mockDB
user, err := service.UserService{}.Create(...)
// assertions ...
}与直接 container.MustGet 的区别
| 维度 | helper.GetDatabase() |
container.MustGet[*gorm.DB]() |
|---|---|---|
| 易读性 | ✅ 短 | ❌ 冗长 |
| 显式依赖 | ❌ 隐藏 | ✅ 类型显眼 |
| 场景 | 业务代码 | 框架代码 / 测试 |
经验法则:业务层代码用 helper,框架层与单元测试用 container.MustGet[T]()。