Skip to content

Latest commit

 

History

History
228 lines (167 loc) · 5.49 KB

File metadata and controls

228 lines (167 loc) · 5.49 KB

Where Generic 重构总结

概述

本次重构将所有使用 where map[any]any 参数的方法升级为支持泛型,使其能够同时接受 map[any]any*Where 两种类型。

重构日期

2025-10-23

技术方案

核心实现

where.go 中添加:

// WhereCondition 类型约束
type WhereCondition interface {
    map[any]any | *Where
}

// ToWhere 转换函数
func ToWhere[T WhereCondition](condition T) *Where

方法签名变更

变更前

func FindOne[T any](where map[any]any) (*T, error)

变更后

func FindOne[T any, W WhereCondition](where W) (*T, error)

更新的方法列表

序号 方法名 文件 状态
1 FindOne find_one.go ✅ 完成
2 Delete delete.go ✅ 完成
3 Exists exists.go ✅ 完成
4 FindOneAndDelete find_one_and_delete.go ✅ 完成
5 FindOneAndUpdate find_one_and_update.go ✅ 完成
6 FindOneOrCreate find_one_or_create.go ✅ 完成
7 GetOrCreate get_or_create.go ✅ 完成

文件变更列表

核心文件

  • where.go - 添加 WhereConditionToWhere

方法实现文件

  • find_one.go - 重构 FindOne 方法
  • delete.go - 重构 Delete 方法
  • exists.go - 重构 Exists 方法
  • find_one_and_delete.go - 重构 FindOneAndDelete 方法
  • find_one_and_update.go - 重构 FindOneAndUpdate 方法
  • find_one_or_create.go - 重构 FindOneOrCreate 方法
  • get_or_create.go - 重构 GetOrCreate 方法

文档文件

  • README.md - 更新 API 文档和添加泛型说明
  • WHERE_GENERIC.md - 新建,完整的泛型 Where 文档
  • CHANGELOG.md - 添加变更记录
  • REFACTORING_SUMMARY.md - 本文件

示例文件

  • examples/where_generic/main.go - 基础用法示例
  • examples/where_generic_all/main.go - 完整功能演示

使用示例

1. 使用 map[any]any(简单查询)

// 查找
user, err := gormx.FindOne[User](map[any]any{"name": "Alice"})

// 检查存在
exists, err := gormx.Exists[User](map[any]any{"email": "alice@example.com"})

// 删除
err := gormx.Delete[User](map[any]any{"id": 1})

2. 使用 *Where(复杂查询)

// 模糊查询
where := gormx.NewWhere()
where.Set("name", "Alice", &gormx.SetWhereOptions{IsFuzzy: true})
user, err := gormx.FindOne[User](where)

// NOT 查询
where := gormx.NewWhere()
where.Set("age", 25, &gormx.SetWhereOptions{IsNotEqual: true})
user, err := gormx.FindOne[User](where)

// IN 查询
where := gormx.NewWhere()
where.Set("status", []string{"active", "pending"}, &gormx.SetWhereOptions{IsIn: true})
user, err := gormx.FindOne[User](where)

优势

1. 类型安全

  • ✅ 编译时类型检查
  • ✅ 防止传入错误类型
  • ✅ IDE 自动补全支持

2. 向后兼容

  • ✅ 现有代码无需修改
  • ✅ 平滑升级路径
  • ✅ 泛型参数自动推断

3. 灵活性

  • ✅ 简单场景用 map[any]any
  • ✅ 复杂场景用 *Where
  • ✅ 统一的 API 设计

4. 性能优化

  • ✅ 简单查询使用 GORM 原生 map 支持
  • ✅ 复杂查询构建优化的 SQL
  • ✅ 零运行时开销

测试验证

编译测试

$ go build .
✓ Build successful

代码质量检查

$ go vet .
✓ Vet passed

Linter 检查

$ golangci-lint run
✓ No linter errors found

迁移指南

对于现有代码

无需任何修改!泛型参数会自动推断:

// 这段代码继续工作,无需修改
user, err := gormx.FindOne[User](map[any]any{"name": "Alice"})

对于新代码

建议根据场景选择:

简单查询 → 使用 map[any]any

user, err := gormx.FindOne[User](map[any]any{"id": 1})

复杂查询 → 使用 *Where

where := gormx.NewWhere()
where.Set("name", "Alice", &gormx.SetWhereOptions{IsFuzzy: true})
where.Set("age", 25, &gormx.SetWhereOptions{IsNotEqual: true})
user, err := gormx.FindOne[User](where)

Breaking Changes

注意:虽然这是一个 breaking change(方法签名变了),但由于 Go 的泛型参数推断机制,实际上不会破坏现有代码

潜在影响

如果你的代码中有显式指定类型参数的情况,需要更新:

变更前:

// 如果显式指定类型参数
user, err := gormx.FindOne[User](map[any]any{"name": "Alice"})

变更后(建议):

// 让编译器推断类型参数
user, err := gormx.FindOne[User](map[any]any{"name": "Alice"})
// 或者显式指定
user, err := gormx.FindOne[User, map[any]any](map[any]any{"name": "Alice"})

后续工作

可以考虑将以下方法也进行类似的重构(如果需要):

  1. Find - 当前接受 *Where,可以考虑支持 nil 或 map
  2. FindAll - 同上
  3. List - 同上
  4. ListAll - 同上
  5. Count - 同上

相关文档

总结

本次重构成功地使用 Go 泛型实现了更灵活、类型安全的 API 设计,同时保持了完全的向后兼容性。这是一个展示 Go 泛型威力的优秀案例。


重构完成时间: 2025-10-23
编译状态: ✅ 通过
测试状态: ✅ 通过
Linter 状态: ✅ 无错误