paging.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package cache
  2. import (
  3. "reflect"
  4. "slices"
  5. "sort"
  6. )
  7. // 分页相关类型定义
  8. type (
  9. // PagingFilterFunc 过滤回调函数类型
  10. // 过滤函数用于决定数据项是否应该包含在查询结果中:
  11. // - 返回值为 true:表示该数据项满足过滤条件,应包含在结果中
  12. // - 返回值为 false:表示该数据项不满足过滤条件,应排除在结果之外
  13. // 例如,过滤价格大于100的商品:
  14. // func(item Product) bool {
  15. // return item.Price > 100
  16. // }
  17. // 过滤特定类型的装备:
  18. // func(item Equipment) bool {
  19. // return item.Type == "武器" || item.Type == "盔甲"
  20. // }
  21. PagingFilterFunc[T any] func(item T) bool
  22. // PagingCompareFunc 比较回调函数类型,用于排序
  23. // 比较函数的返回值定义了两个元素在排序中的相对位置:
  24. // - 返回值 < 0:表示a应该排在b之前
  25. // - 返回值 == 0:表示a和b在排序中地位相等
  26. // - 返回值 > 0:表示a应该排在b之后
  27. // 例如,实现升序排序:
  28. // func(a, b int) int {
  29. // return a - b
  30. // }
  31. // 实现降序排序:
  32. // func(a, b int) int {
  33. // return b - a
  34. // }
  35. PagingCompareFunc[T any] func(a, b T) int
  36. // Paging 泛型分页数据结构
  37. Paging[T any] struct {
  38. data []T
  39. }
  40. )
  41. // NewPaging 创建新的Paging实例
  42. func NewPaging[T any]() *Paging[T] {
  43. return &Paging[T]{
  44. data: make([]T, 0),
  45. }
  46. }
  47. // Add 添加数据到Paging
  48. func (p *Paging[T]) Add(item T) {
  49. p.data = append(p.data, item)
  50. }
  51. // AddAll 批量添加数据到Paging
  52. func (p *Paging[T]) AddAll(items []T) {
  53. p.data = append(p.data, items...)
  54. }
  55. // 根据指定的 comparator fn排序
  56. func (p *Paging[T]) Sort(comparator PagingCompareFunc[T]) {
  57. if comparator == nil || p.Count() <= 1 {
  58. return
  59. }
  60. sorted := make([]T, 0, len(p.data))
  61. copy(sorted, p.data)
  62. sort.SliceStable(sorted, func(i, j int) bool {
  63. return comparator(sorted[i], sorted[j]) < 0
  64. })
  65. p.data = sorted
  66. }
  67. // Query 查询方法,支持分页、过滤和排序
  68. // filter参数为本次查询的过滤条件,comparator参数为本次查询的比较条件
  69. func (p *Paging[T]) Query(pageNum, pageSize int32, filter PagingFilterFunc[T], comparator PagingCompareFunc[T]) (total int32, data []T) {
  70. // 验证参数
  71. if pageNum < 1 {
  72. pageNum = 1
  73. }
  74. if pageSize < 1 {
  75. pageSize = 10
  76. }
  77. // 应用过滤
  78. filteredData := make([]T, 0, len(p.data))
  79. for _, item := range p.data {
  80. if filter == nil || filter(item) {
  81. filteredData = append(filteredData, item)
  82. }
  83. }
  84. // 计算总数
  85. total = int32(len(filteredData))
  86. if total == 0 {
  87. return 0, nil
  88. }
  89. // 应用排序
  90. if comparator != nil {
  91. sort.SliceStable(filteredData, func(i, j int) bool {
  92. return comparator(filteredData[i], filteredData[j]) < 0
  93. })
  94. }
  95. // 计算分页
  96. start := (pageNum - 1) * pageSize
  97. if start >= total {
  98. return total, nil
  99. }
  100. end := min(start+pageSize, total)
  101. return total, filteredData[start:end]
  102. }
  103. // Clear 清空所有数据
  104. func (p *Paging[T]) Clear() {
  105. p.data = make([]T, 0)
  106. }
  107. // Count 获取总数据量
  108. func (p *Paging[T]) Count() int32 {
  109. return int32(len(p.data))
  110. }
  111. // IndexOf 返回元素 item 在内部切片中的下标,找不到返回 -1。
  112. // 使用 reflect.DeepEqual 进行比较,适用于大多数类型。
  113. func (p *Paging[T]) IndexOf(item T) int {
  114. for i, v := range p.data {
  115. if reflect.DeepEqual(v, item) {
  116. return i
  117. }
  118. }
  119. return -1
  120. }
  121. // Remove 删除第一次出现的指定元素,删除成功返回 被删除的元素 和 true,否则返回零值和 false。
  122. func (p *Paging[T]) Remove(item T) (T, bool) {
  123. idx := p.IndexOf(item)
  124. var zero T
  125. if idx == -1 {
  126. return zero, false
  127. }
  128. return p.RemoveAt(idx)
  129. }
  130. // RemoveAt 删除指定下标的元素(按切片索引),成功返回 被删除的元素 和 true,索引越界返回 零值 和 false。
  131. func (p *Paging[T]) RemoveAt(index int) (T, bool) {
  132. var zero T
  133. if index < 0 || index >= len(p.data) {
  134. return zero, false
  135. }
  136. removed := p.data[index]
  137. p.data = slices.Delete(p.data, index, index+1)
  138. return removed, true
  139. }
  140. // ForEach 遍历所有元素
  141. func (p *Paging[T]) ForEach(f func(item T)) {
  142. for _, item := range p.data {
  143. f(item)
  144. }
  145. }