四个基础设施包:config 用 viper 加载合并多 yaml;database 管理 GORM 连接池并强制注册审计回调;redis 初始化 go-redis v9 客户端;cache 在 redis 之上提供 group:key 格式缓存助手。启动顺序固定为 config.Load → database.Init → redis.Init → cache 等下游。
关键导出
config.Config struct{Server, Datasource, Redis, SAToken, CORS, XSS, ..., SMS, Social}config.Load(paths ...string)读取并合并 yaml 写包级实例(失败 panic)config.Get() *Config(未 Load panic)- 各子配置
ServerConfig / DatasourceConfig / RedisConfig / SATokenConfig / CaptchaConfig / APIEncryptConfig / SocialConfig及DefaultXxx()默认值与validate() database.New(cfg config.DatasourceConfig) (*gorm.DB, error)/Init()/DB() *gorm.DB/Close(db)/CloseDefault()redis.New(cfg config.RedisConfig) (*goredis.Client, error)/Init()/Client()/Close(client)/SetClient(client) (restore func())cache.Get(ctx, group, key, dest any) (bool, error)(命中/miss/故障三态)cache.Put(ctx, group, key, val, ttl) error(ttl=0不过期)cache.Evict(ctx, group, key)/EvictGroup(ctx, group)(SCAN 分批删,不用KEYS)cache.GetOrSet(ctx, group, key, ttl, dest, load func(ctx)(any,error))(singleflight 合并并发 miss)
典型用法
go
// cmd/standalone/main.go:35
config.Load("configs/application.yaml", "configs/standalone.yaml")
cfg := config.Get().Datasource
// internal/system/service/client_service.go:70
repository.NewClientRepository(database.DB()).SelectPageList(ctx, q, page)
// internal/system/service/config_service.go:71
if hit, _ := cache.Get(ctx, constant.CacheSysConfig, configKey, &cached); hit {
return cached, nil
}
_ = cache.Put(ctx, constant.CacheSysConfig, configKey, value, constant.CacheTTLSysConfig)
_ = cache.Evict(ctx, constant.CacheSysConfig, b.ConfigKey)坑/约定
WARNING
config.Load先用DefaultXxx().setDefaults(v)注入默认值再读 yaml,缺失字段有兜底;validate()串联校验所有子配置,任一失败即 panic(启动期 fail-fast)。databaseGORM 配置SingularTable:true(表名单数)、SkipDefaultTransaction:true、DisableForeignKeyConstraintWhenMigrating:true;New内部 强制调repository.RegisterAuditCallbacks(db),任何 main 都无法漏掉;命名策略单数表名,实体无需TableName()。redis.Init失败 panic;ping 探活失败时也会client.Close()回收连接池;SetClient返回 restore 闭包, 仅供测试注入。cache.Get返回(bool, error),不能_ =——miss 与故障语义不同。Redis 故障时GetOrSet的load仍会被调用(fail-open,错误透传)。序列化统一走pkg/jsonx(保持 int64 字符串契约)。EvictGroup用 SCAN+pipeline Del 避免阻塞。 :::
相关页:/architecture/request-flow、/getting-started/config、/pkg-reference/repository。