lazy.go
1.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package tool
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"gitlab.fjmaimaimai.com/allied-creation/su-micro/pkg/transaction"
"reflect"
)
type LazyLoadService[K comparable, T any] struct {
FoundMap map[K]T // 已找到对象Map
NotFoundMap map[K]T // 未找到对象Map
load func(context.Context, transaction.Conn, K) (T, error)
}
func NewLazyLoadService[K comparable, T any](load func(context.Context, transaction.Conn, K) (T, error)) *LazyLoadService[K, T] {
return &LazyLoadService[K, T]{
FoundMap: map[K]T{},
NotFoundMap: map[K]T{},
load: load,
}
}
func (s *LazyLoadService[K, T]) Load(ctx context.Context, conn transaction.Conn, k K) (T, error) {
if isEmptyOrZeroValue(k) {
var t T
return t, fmt.Errorf("empty key ‘%v’", k)
}
if v, ok := s.NotFoundMap[k]; ok {
return v, sqlx.ErrNotFound
}
if v, ok := s.FoundMap[k]; ok {
return v, nil
}
if v, err := s.load(ctx, conn, k); err != nil {
if errors.Is(err, sqlx.ErrNotFound) {
s.NotFoundMap[k] = v
}
return v, err
} else {
s.FoundMap[k] = v
return v, nil
}
}
func isEmptyOrZeroValue(i interface{}) bool {
if i == nil {
return true // 如果接口为空,返回true
}
// 使用反射判断接口的值是否为零值
v := reflect.ValueOf(i)
switch v.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
default:
return false // 其他类型默认不为空
}
}