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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
package store
import (
"sync/atomic"
)
type (
Getter interface {
Get() (string, error)
}
GetFunc func() (string, error)
Setter interface {
Set(string) error
}
SetFunc func(string) error
// Singleton is a thread-safe abstraction to load and store a string
Singleton interface {
Getter
Setter
}
SingletonAdapter struct {
GetFunc
SetFunc
}
SingletonDecorator interface {
Decorate(Singleton) Singleton
}
Error string
)
func (err Error) Error() string { return string(err) }
const ErrNotFound = Error("value not found in store")
func (f GetFunc) Get() (string, error) { return f() }
func (f SetFunc) Set(s string) error { return f(s) }
func NewInMemorySingleton() Singleton {
var value atomic.Value
return &SingletonAdapter{
func() (string, error) {
x := value.Load()
if x == nil {
return "", ErrNotFound
}
return x.(string), nil
},
func(s string) error {
value.Store(s)
return nil
},
}
}
type (
GetFuncDecorator func(Getter, string, error) (string, error)
SetFuncDecorator func(Setter, string, error) error
)
func DoSet() SetFuncDecorator {
return func(s Setter, v string, _ error) error {
return s.Set(v)
}
}
func (f SetFuncDecorator) AndThen(f2 SetFuncDecorator) SetFuncDecorator {
return func(s Setter, v string, err error) error {
err = f(s, v, err)
if err != nil {
return err
}
return f2(s, v, nil)
}
}
func (f SetFuncDecorator) Decorate(s Singleton) Singleton {
if f == nil {
return s
}
return &SingletonAdapter{
s.Get,
SetFunc(func(v string) error {
return f(s, v, nil)
}),
}
}
func DoGet() GetFuncDecorator {
return func(s Getter, _ string, _ error) (string, error) {
return s.Get()
}
}
func (f GetFuncDecorator) AndThen(f2 GetFuncDecorator) GetFuncDecorator {
return func(s Getter, v string, err error) (string, error) {
v, err = f(s, v, err)
if err != nil {
return v, err
}
return f2(s, v, nil)
}
}
func (f GetFuncDecorator) Decorate(s Singleton) Singleton {
if f == nil {
return s
}
return &SingletonAdapter{
GetFunc(func() (string, error) {
return f(s, "", nil)
}),
s.Set,
}
}
func DecorateSingleton(s Singleton, ds ...SingletonDecorator) Singleton {
for _, d := range ds {
if d != nil {
s = d.Decorate(s)
}
}
return s
}
// GetOrPanic curries the result of a Getter invocation: the returned func only ever returns the string component when
// the error component of the underlying Get() call is nil. If Get() generates an error then the curried func panics.
func GetOrPanic(g Getter) func() string {
return func() string {
v, err := g.Get()
if err != nil {
panic(err)
}
return v
}
}
func GetIgnoreErrors(g Getter) func() string {
return func() string {
v, _ := g.Get()
return v
}
}
// SetOrPanic curries the result of a Setter invocation: the returned func only ever returns normally when the error
// component of the underlying Set() call is nil. If Set() generates an error then the curried func panics.
func SetOrPanic(s Setter) func(v string) {
return func(v string) {
err := s.Set(v)
if err != nil {
panic(err)
}
}
}
|