如何将数据库连接集成到util包validator,实现校验时查询数据库
改造方案
核心思路是通过依赖注入将service层实例传入自定义校验器,避免使用全局DB变量导致的耦合问题,具体步骤如下:
第一步:扩展自定义校验器结构体,注入依赖
修改validator.go中的CustomValidator结构体,新增需要用到的service层字段(可根据校验需求添加多个不同的service实例):
package utils import ( "v/pkg/service" // 替换为你项目实际的service包路径 "github.com/go-playground/validator/v10" ) // CustomValidator 第三方校验器的类型定义 type CustomValidator struct { Validator *validator.Validate UserService *service.UserService // 注入封装了DB操作的service实例 } // Init 初始化校验器,注册自定义校验规则 func (cv *CustomValidator) Init() { // 注册名称重复校验规则 cv.Validator.RegisterValidation("name_unique", func(fl validator.FieldLevel) bool { // 获取待校验的名称值 checkName := fl.Field().String() // 调用service方法查询名称是否已存在 isExists, err := cv.UserService.CheckNameExists(checkName) if err != nil { // 可根据需求打印错误日志,查询失败默认返回校验不通过 return false } // 名称不存在则校验通过 return !isExists }) } // Validate 执行数据校验 func (cv *CustomValidator) Validate(i interface{}) error { return cv.Validator.Struct(i) }
第二步:调整main函数初始化顺序
需要按顺序初始化DB连接、service实例、校验器,将service实例注入校验器后再绑定到echo框架:
package main import ( "v/utils" "v/pkg/service" "v/pkg/db" // 替换为你项目实际的DB初始化包 "github.com/labstack/echo/v4" "github.com/go-playground/validator/v10" ) func init() { env.Load(".env") } func main() { e := echo.New() // 1. 初始化数据库连接(替换为你项目实际的DB初始化逻辑) dbInstance, err := db.InitDB() if err != nil { panic(err) } // 2. 初始化service实例,传入DB连接 userService := service.NewUserService(dbInstance) // 3. 初始化自定义校验器,注入service依赖 customValidator := &utils.CustomValidator{ Validator: validator.New(), UserService: userService, } // 4. 执行校验器初始化,注册自定义校验规则 customValidator.Init() // 5. 将校验器绑定到echo框架 e.Validator = customValidator e.Logger.Fatal(e.Start("1234")) }
可选优化:用接口降低耦合
如果需要降低utils包和service包的直接依赖,可以在utils包中定义最小接口,只声明校验需要用到的方法,方便后续单测时mock:
// 在validator.go中定义接口 type NameChecker interface { CheckNameExists(name string) (bool, error) } // 结构体字段改用接口类型 type CustomValidator struct { Validator *validator.Validate NameChecker NameChecker // 只要实现了CheckNameExists方法的类型都可以注入 }
注意事项
- 高频接口的重复校验建议加本地缓存或者Redis缓存,减少DB查询压力
- 校验通过后的插入操作需要加唯一索引兜底,避免并发场景下校验和插入之间有其他请求写入相同数据
- 校验逻辑中如果遇到DB查询错误,不要直接返回校验不通过,可以根据业务场景决定是返回错误还是降级处理
内容的提问来源于stack exchange,提问作者Shawn Yeung
相关产品推荐
相关产品推荐

