Skip to content

Instantly share code, notes, and snippets.

@preytaren
Last active March 22, 2021 10:44
Show Gist options
  • Save preytaren/8fa234a4951d88dbdc8e2bdc2f363895 to your computer and use it in GitHub Desktop.
Save preytaren/8fa234a4951d88dbdc8e2bdc2f363895 to your computer and use it in GitHub Desktop.
Future Pattern in Go
package cacheutils
import (
"sync"
"time"
)
const FUTURETIMEOUT = 5 * time.Second
type Future interface {
Get(string) interface{}
}
type StringFuture struct {
sync.RWMutex
inner map[string][]chan interface{}
f func(string) (interface{}, error)
}
func NewStringFuture(f func(string) (interface{}, error)) Future {
sf := new(StringFuture)
sf.RWMutex = sync.RWMutex{}
sf.inner = make(map[string][]chan interface{})
sf.f = f
return sf
}
func (sf *StringFuture) Get(key string) interface{} {
sf.Lock()
_, ok := sf.inner[key]
if ok {
ch := make(chan interface{}, 1)
sf.inner[key] = append(sf.inner[key], ch)
sf.Unlock()
ticker := time.NewTicker(FUTURETIMEOUT)
defer ticker.Stop()
select {
case r :=<- ch:
return r
case <- ticker.C:
return nil
}
} else {
sf.inner[key] = make([]chan interface{}, 0, 4)
sf.Unlock()
res, err := sf.f(key)
sf.Lock()
chList := sf.inner[key]
delete(sf.inner, key)
sf.Unlock()
if err != nil {
go func() {
for _, ch := range chList {
ch <- res
}
}()
return nil
}
go func() {
for _, ch := range chList {
ch <- res
}
}()
return res
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment