-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypedsf.go
82 lines (74 loc) · 1.95 KB
/
typedsf.go
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
71
72
73
74
75
76
77
78
79
80
81
82
package typedsf
import (
"fmt"
"golang.org/x/sync/singleflight"
)
// Result is the same as singleflight.Result, but with type information
type Result[T any] struct {
Val T
Err error
Shared bool
}
// Group is the same as singleflight.Group, but with type information
type Group[T any] struct {
sf *singleflight.Group
}
func (g *Group[T]) setSingleflight() {
if g.sf == nil {
g.sf = new(singleflight.Group)
}
}
// Do is the same as singleflight.Group, but with type information. If for some
// reason an incorrect type is returned by `fn` then an error will be returned
// to all callers.
func (g *Group[T]) Do(key string, fn func() (T, error)) (T, error, bool) {
g.setSingleflight()
val, err, shared := g.sf.Do(key, func() (interface{}, error) {
return fn()
})
var typedVal T // create default
if tempVal, ok := val.(T); !ok {
return typedVal, fmt.Errorf("typedsf: expected %T but got %T", typedVal, val), shared
} else {
return tempVal, err, shared
}
}
// DoChan is the same as singleflight.Group, but with type information. If for some
// reason an incorrect type is returned by `fn` then an error will be returned
// to all callers via the channel.
//
// The returned channel is not closed.
func (g *Group[T]) DoChan(key string, fn func() (T, error)) <-chan Result[T] {
g.setSingleflight()
ch := make(chan Result[T], 1)
go func() {
ch2 := g.sf.DoChan(key, func() (interface{}, error) {
return fn()
})
res := <-ch2
var typedVal T
if res.Val != nil {
if tempVal, ok := res.Val.(T); !ok {
ch <- Result[T]{
Val: typedVal, // default
Err: fmt.Errorf("typedsf: expected %T but got %T", typedVal, res.Val),
Shared: res.Shared,
}
return
} else {
typedVal = tempVal
}
}
ch <- Result[T]{
Val: typedVal,
Err: res.Err,
Shared: res.Shared,
}
}()
return ch
}
// Forget is the same as singleflight.Group
func (g *Group[T]) Forget(key string) {
g.setSingleflight()
g.sf.Forget(key)
}