Skip to content

Instantly share code, notes, and snippets.

@jonbodner
Created December 28, 2017 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonbodner/170e240a7a753cec511b731c57cbcdc1 to your computer and use it in GitHub Desktop.
Save jonbodner/170e240a7a753cec511b731c57cbcdc1 to your computer and use it in GitHub Desktop.
type outExp struct {
out []reflect.Value
expiry time.Time
}
func Cacher(f interface{}, expiration time.Duration) (interface{}, error) {
ft := reflect.TypeOf(f)
if ft.Kind() != reflect.Func {
return nil, errors.New("Only for functions")
}
inType, err := buildInStruct(ft)
if err != nil {
return nil, err
}
if ft.NumOut() == 0 {
return nil, errors.New("Must have at least one returned value")
}
m := map[interface{}]outExp{}
fv := reflect.ValueOf(f)
cacher := reflect.MakeFunc(ft, func(args []reflect.Value) []reflect.Value {
iv := reflect.New(inType).Elem()
for k, v := range args {
iv.Field(k).Set(v)
}
ivv := iv.Interface()
ov, ok := m[ivv]
now := time.Now()
if !ok || ov.expiry.Before(now) {
ov.out = fv.Call(args)
ov.expiry = now.Add(expiration)
m[ivv] = ov
}
return ov.out
})
return cacher.Interface(), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment