# go-validate **Repository Path**: go-framework_llllllh/go-validate ## Basic Information - **Project Name**: go-validate - **Description**: validate验证框架。适合多类型验证,验证逻辑与业务逻辑分离,扩展验证规则登场景。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-20 - **Last Updated**: 2025-06-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go-validate #### 介绍 validate验证框架。适合多类型验证,验证逻辑与业务逻辑分离,扩展验证规则登场景。 #### 适用场景 这种验证模式特别适合: * 需要验证多种不同类型的场景 * 希望验证逻辑与业务逻辑分离的架构 * 需要灵活扩展验证规则的系统 常用于API请求参数的验证,可以很好地与框架的其他组件配合工作。 #### 设计优点 1. **接口隔离**:验证逻辑与业务逻辑分离 2. **单一职责**:每个类型负责自己的验证规则 3. **易于测试**:可以单独测试验证逻辑 4. **可组合性**:可以与其他验证库结合使用 #### 历程 - 在原有的业务代码逻辑之前,添加验证函数校验。不推荐 - 将验证逻辑与业务逻辑分离,函数转换为对象的方法,在业务逻辑执行前,执行对象的验证方法。接口隔离,单一职责,但未实现结果缺乏...。一般推荐 - 将所有类型对象的验证方法抽象为接口。推荐 - xx #### Q&A Q:验证函数校验太为基础,不采用很正常。但是使用验证方法已经优化了,为什还要加入接口这一特性? 设计 `Validator` 接口和通用 `validate` 函数的主要目的是为了实现更优雅的 **抽象** 和 **解耦**。 以下为该方式的优势: 1. **统一验证入口** `validate.go` 提供统一的验证入口,**隐藏具体实现细节**,调用方无需关心对象是否有验证方法: ``` // 调用方代码(简洁,不依赖具体类型) err := validate(obj) // 统一调用方式 ``` 对比直接调用: ``` // 需要明确知道obj有Validate()方法 err := obj.Validate() ``` **场景价值**:当需要验证多种不同类型的对象时,调用方代码可以保持一致,不需要针对不同类型写不同验证逻辑。 2. **非侵入式验证** `validate` 函数通过接口检查实现 **"鸭子类型"** 的验证: * 如果对象实现了 `Validator` 接口,则验证; * 如果未实现,则跳过(返回 `nil`)。 **优势**: * 不强制所有对象必须实现验证逻辑。 * 兼容既有代码,无需改造旧对象。 ``` // 旧代码:没有Validate()方法 → 自动跳过验证 type LegacyObj struct { /*...*/ } // 新代码:实现Validator接口 → 自动支持验证 type NewObj struct { /*...*/ } func (o NewObj) Validate() error { /*...*/ } ``` 3. **依赖抽象而非具体** 通过接口抽象,**高层模块不依赖具体对象**,而是依赖 `Validator` 接口。例如: ``` func Process(obj any) error { // 不关心obj的具体类型,只关心它能否验证 if err := validate(obj); err != nil { return err } // ...其他处理 } ``` **扩展性**:未来新增对象类型时,只要实现 `Validator` 接口即可兼容现有逻辑,无需修改 `Process` 函数。 4. **与框架集成** 在 `go-zero` 这类框架中,`validate` 函数通常被集成到 **请求解析层** 或 **中间件** 中,自动处理验证。例如: ``` // 框架内部可能这样使用: func ParseRequest(req *http.Request, v any) error { if err := json.Unmarshal(body, v); err != nil { return err } return validate(v) // 自动触发验证 } ``` **用户只需**: ``` type UserRequest struct { /*...*/ } func (u UserRequest) Validate() error { /*...*/ } // 框架自动调用Validate() var req UserRequest ParseRequest(httpReq, &req) ``` 5. **逻辑分层清晰** * **业务层**:实现 `Validate()` 方法,定义具体规则。 * **基础设施层**:提供 `validate` 函数,处理验证流程。 * **调用方**:无需关心验证细节。 Q:何时直接调用 `obj.Validate()`? 如果只是 **简单场景**(例如单一类型、无需框架集成),直接调用 `obj.Validate()` 更直接。但在以下情况下,接口+通用函数的方式更有优势: 1. 需要统一处理多种对象类型。 2. 希望与框架(如 `go-zero`)深度集成。 3. 需要保持代码扩展性,避免未来重构。